unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Po Lu <luangruo@yahoo.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: Allowing point to be outside the window?
Date: Sat, 04 Dec 2021 19:18:38 +0800	[thread overview]
Message-ID: <87czmcvcs1.fsf@yahoo.com> (raw)
In-Reply-To: <8735ne4e0e.fsf@yahoo.com> (Po Lu's message of "Tue, 30 Nov 2021 09:40:33 +0800")

[-- Attachment #1: Type: text/plain, Size: 743 bytes --]

Po Lu <luangruo@yahoo.com> writes:

> Eli Zaretskii <eliz@gnu.org> writes:
>
>> It might also be called by redisplay,
>
> That is what I'm worried about, thanks.
>
>> ... it makes very little sense to me to introduce such a feature only
>> for the sake of pixel-wise scrolling.  We should allow such a mode
>> with all the Emacs commands, not just in pixel-wise scrolling.  And
>> anyway, Emacs might call scrolling commands as part of other commands,
>> not just because the user types C-v.
>
> Makes sense, I will work on it.

I haven't figured out most of the user level command things, but here's
a patch that allows point to be outside a window.

Some redisplay optimizations are disabled, but I hope to solve that
soon.

WDYT?  Thanks.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Make-it-possible-for-point-to-appear-outside-a-windo.patch --]
[-- Type: text/x-patch, Size: 13173 bytes --]

From f2295fbfceff3ef0db91c9c5b9e5155fefe12697 Mon Sep 17 00:00:00 2001
From: Po Lu <luangruo@yahoo.com>
Date: Sat, 4 Dec 2021 18:33:53 +0800
Subject: [PATCH] Make it possible for point to appear outside a window

* src/window.h (struct window): New field `cursor_visible_p'.

* src/xdisp.c (redisplay_internal, redisplay_window): Allow
point to appear outside the window.

(set_cursor_from_row): Set cursor_visible_p appropriately.
(try_window_id)
(try_cursor_movement): Disable optimization when point is
allowed to be invisible.

(display_and_set_cursor): Erase cursor if invisible.

(try_window): Allow some things.
(syms_of_xdisp) <keep-point-visible>: New variable.
---
 src/window.h |   4 ++
 src/xdisp.c  | 194 ++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 150 insertions(+), 48 deletions(-)

diff --git a/src/window.h b/src/window.h
index 2400c422c1..e9528ff02f 100644
--- a/src/window.h
+++ b/src/window.h
@@ -445,6 +445,10 @@ #define WINDOW_H_INCLUDED
        window.  */
     bool_bf suspend_auto_hscroll : 1;
 
+    /* True if the cursor is supposed to be visible in this
+       window.  */
+    bool_bf cursor_visible_p : 1;
+
     /* Amount by which lines of this window are scrolled in
        y-direction (smooth scrolling).  */
     int vscroll;
diff --git a/src/xdisp.c b/src/xdisp.c
index 7ca3977200..7a0949d514 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -16118,6 +16118,8 @@ #define AINC(a,i)							\
   tlbufpos = this_line_start_pos;
   tlendpos = this_line_end_pos;
   if (!consider_all_windows_p
+      /* TODO: enable this optimization.  */
+      && keep_point_visible
       && CHARPOS (tlbufpos) > 0
       && !w->update_mode_line
       && !current_buffer->clip_changed
@@ -16989,6 +16991,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
      comes from a text property, not from an overlay.  */
   bool string_from_text_prop = false;
 
+  w->cursor_visible_p = false;
+
   /* Don't even try doing anything if called for a mode-line or
      header-line or tab-line row, since the rest of the code isn't
      prepared to deal with such calamities.  */
@@ -17575,6 +17579,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 	CHARPOS (this_line_start_pos) = 0;
     }
 
+  w->cursor_visible_p = true;
   return true;
 }
 
@@ -18183,6 +18188,10 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
     return rc;
 #endif
 
+  /* TODO: enable this optimization.  */
+  if (!keep_point_visible)
+    return CURSOR_MOVEMENT_CANNOT_BE_USED;
+
   /* Previously, there was a check for Lisp integer in the
      if-statement below. Now, this field is converted to
      ptrdiff_t, thus zero means invalid position in a buffer.  */
@@ -18770,6 +18779,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       clear_glyph_matrix (w->desired_matrix);
     }
 
+  debug_method_add (w, "real redisplay starts");
+
   /* Otherwise set up data on this window; select its buffer and point
      value.  */
   /* Really select the buffer, for the sake of buffer-local
@@ -18964,34 +18975,39 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 
       if (w->cursor.vpos < 0)
 	{
-	  /* If point does not appear, try to move point so it does
-	     appear.  The desired matrix has been built above, so we
-	     can use it here.  First see if point is in invisible
-	     text, and if so, move it to the first visible buffer
-	     position past that.  */
-	  struct glyph_row *r = NULL;
-	  Lisp_Object invprop =
-	    get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
-					   Qnil, NULL);
-
-	  if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
+	  if (!keep_point_visible)
+	    w->cursor_visible_p = false;
+	  else
 	    {
-	      ptrdiff_t alt_pt;
-	      Lisp_Object invprop_end =
-		Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
-						   Qnil, Qnil);
+	      /* If point does not appear, try to move point so it does
+		 appear.  The desired matrix has been built above, so we
+		 can use it here.  First see if point is in invisible
+		 text, and if so, move it to the first visible buffer
+		 position past that.  */
+	      struct glyph_row *r = NULL;
+	      Lisp_Object invprop =
+		get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
+					       Qnil, NULL);
+
+	      if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
+		{
+		  ptrdiff_t alt_pt;
+		  Lisp_Object invprop_end =
+		    Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
+						       Qnil, Qnil);
 
-	      if (FIXNATP (invprop_end))
-		alt_pt = XFIXNAT (invprop_end);
-	      else
-		alt_pt = ZV;
-	      r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
-				      NULL, 0);
+		  if (FIXNATP (invprop_end))
+		    alt_pt = XFIXNAT (invprop_end);
+		  else
+		    alt_pt = ZV;
+		  r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
+					  NULL, 0);
+		}
+	      if (r)
+		new_vpos = MATRIX_ROW_BOTTOM_Y (r);
+	      else	/* Give up and just move to the middle of the window.  */
+		new_vpos = window_box_height (w) / 2;
 	    }
-	  if (r)
-	    new_vpos = MATRIX_ROW_BOTTOM_Y (r);
-	  else	/* Give up and just move to the middle of the window.  */
-	    new_vpos = window_box_height (w) / 2;
 	}
 
       if (!cursor_row_fully_visible_p (w, false, false, false))
@@ -19223,10 +19239,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	  IF_DEBUG (debug_method_add (w, "1"));
 	  clear_glyph_matrix (w->desired_matrix);
 	  if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
-	    /* -1 means we need to scroll.
-	       0 means we need new matrices, but fonts_changed
-	       is set in that case, so we will detect it below.  */
-	    goto try_to_scroll;
+	    {
+	      /* -1 means we need to scroll.
+		 0 means we need new matrices, but fonts_changed
+		 is set in that case, so we will detect it below.  */
+	      goto try_to_scroll;
+	    }
 	}
 
       if (f->fonts_changed)
@@ -19253,9 +19271,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
 	clear_glyph_matrix (w->desired_matrix);
     }
 
+  if (!keep_point_visible)
+    goto maybe_try_window;
+
  try_to_scroll:
 
-  /* Redisplay the mode line.  Select the buffer properly for that.  */
+ /* Redisplay the mode line.  Select the buffer properly for that.  */
   if (!update_mode_line)
     {
       update_mode_line = true;
@@ -19317,6 +19338,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   /* Determine the window start relative to point.  */
   init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
   it.current_y = it.last_visible_y;
+
   if (centering_position < 0)
     {
       ptrdiff_t margin_pos = CHARPOS (startp);
@@ -19584,6 +19606,53 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       centering_position = 0;
       goto recenter;
     }
+  goto done;
+
+ maybe_try_window:
+
+  /* Set the window start position here explicitly if it is outside
+     the accessible portion of the buffer.  */
+
+  if (CHARPOS (startp) < BEGV
+      || CHARPOS (startp) > ZV)
+    {
+      if (CHARPOS (startp) < BEGV)
+	set_marker_both (w->start, Qnil, BEGV, BEGV_BYTE);
+      else
+	set_marker_both (w->start, Qnil, ZV, ZV_BYTE);
+
+      SET_TEXT_POS_FROM_MARKER (startp, w->start);
+
+      /* Run scroll hooks.  */
+      startp = run_window_scroll_functions (window, startp);
+    }
+
+  /* We invoke try_window and try_window_reusing_current_matrix below,
+     and they manipulate the bidi cache.  Save and restore the cache
+     state of our iterator, so we could continue using it after that.  */
+  itdata = bidi_shelve_cache ();
+
+  /* Redisplay the window.  */
+  use_desired_matrix = false;
+  if (!current_matrix_up_to_date_p
+      || windows_or_buffers_changed
+      || f->cursor_type_changed
+      /* Don't use try_window_reusing_current_matrix in this case
+	 because it can have changed the buffer.  */
+      || !NILP (Vwindow_scroll_functions)
+      || !just_this_one_p
+      || MINI_WINDOW_P (w)
+      || !(used_current_matrix_p
+	   = try_window_reusing_current_matrix (w)))
+    use_desired_matrix = (try_window (window, startp, 0) == 1);
+
+  bidi_unshelve_cache (itdata, false);
+
+  /* If new fonts have been loaded (due to fontsets), give up.  We
+     have to start a new redisplay since we need to re-adjust glyph
+     matrices.  */
+  if (f->fonts_changed)
+    goto need_larger_matrices;
 
  done:
 
@@ -19591,6 +19660,12 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
   w->start_at_line_beg = (CHARPOS (startp) == BEGV
 			  || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
 
+  if (!keep_point_visible
+      && (!w->cursor_visible_p
+	  || w->cursor.vpos == -1)
+      && w->phys_cursor_on_p)
+    erase_phys_cursor (w);
+
   /* Display the mode line, header line, and tab-line, if we must.  */
   if ((update_mode_line
        /* If window not full width, must redo its mode line
@@ -19801,6 +19876,8 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
   struct frame *f = XFRAME (w->frame);
   int cursor_vpos = w->cursor.vpos;
 
+  debug_method_add (w, "try_window");
+
   /* Make POS the new window start.  */
   set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
 
@@ -19960,6 +20037,10 @@ try_window_reusing_current_matrix (struct window *w)
     return false;
 #endif
 
+  /* TODO: enable this optimization.  */
+  if (!keep_point_visible)
+    return false;
+
   /* The variable new_start now holds the new window start.  The old
      start `start' can be determined from the current matrix.  */
   SET_TEXT_POS_FROM_MARKER (new_start, w->start);
@@ -20875,6 +20956,8 @@ #define GIVE_UP(X) return 0
 	  row = row_containing_pos (w, PT, r0, NULL, 0);
 	  if (row)
 	    set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+	  else
+	    w->cursor_visible_p = false;
 	  return 1;
 	}
     }
@@ -20915,6 +20998,8 @@ #define GIVE_UP(X) return 0
 	  row = row_containing_pos (w, PT, r0, NULL, 0);
 	  if (row)
 	    set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
+	  else
+	    w->cursor_visible_p = false;
 	  return 2;
 	}
     }
@@ -21152,6 +21237,8 @@ #define GIVE_UP(X) return 0
 				    last_unchanged_at_beg_row + 1, 0);
 	  if (row)
 	    set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
+	  else
+	    w->cursor_visible_p = false;
 	}
 
       /* Start from first_unchanged_at_end_row looking for PT.  */
@@ -21162,6 +21249,8 @@ #define GIVE_UP(X) return 0
 	  if (row)
 	    set_cursor_from_row (w, row, w->current_matrix, delta,
 				 delta_bytes, dy, dvpos);
+	  else
+	    w->cursor_visible_p = false;
 	}
 
       /* Give up if cursor was not found.  */
@@ -21173,24 +21262,25 @@ #define GIVE_UP(X) return 0
     }
 
   /* Don't let the cursor end in the scroll margins.  */
-  {
-    int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
-    int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
-
-    if ((w->cursor.y < this_scroll_margin
-	 && CHARPOS (start) > BEGV)
-	/* Old redisplay didn't take scroll margin into account at the bottom,
-	   but then global-hl-line-mode doesn't scroll.  KFS 2004-06-14 */
-	|| (w->cursor.y
-	    + (cursor_row_fully_visible_p (w, false, true, true)
-	       ? 1
-	       : cursor_height + this_scroll_margin)) > it.last_visible_y)
-      {
-	w->cursor.vpos = -1;
-	clear_glyph_matrix (w->desired_matrix);
-	return -1;
-      }
-  }
+  if (w->cursor_visible_p)
+    {
+      int this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
+      int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
+
+      if ((w->cursor.y < this_scroll_margin
+	   && CHARPOS (start) > BEGV)
+	  /* Old redisplay didn't take scroll margin into account at the bottom,
+	     but then global-hl-line-mode doesn't scroll.  KFS 2004-06-14 */
+	  || (w->cursor.y
+	      + (cursor_row_fully_visible_p (w, false, true, true)
+		 ? 1
+		 : cursor_height + this_scroll_margin)) > it.last_visible_y)
+	{
+	  w->cursor.vpos = -1;
+	  clear_glyph_matrix (w->desired_matrix);
+	  return -1;
+	}
+    }
 
   /* Scroll the display.  Do it before changing the current matrix so
      that xterm.c doesn't get confused about where the cursor glyph is
@@ -32387,6 +32477,10 @@ display_and_set_cursor (struct window *w, bool on,
 	      && new_cursor_width != w->phys_cursor_width)))
     erase_phys_cursor (w);
 
+  if (!w->cursor_visible_p
+      || w->cursor.vpos == -1)
+    return;
+
   /* Don't check phys_cursor_on_p here because that flag is only set
      to false in some cases where we know that the cursor has been
      completely erased, to avoid the extra work of erasing the cursor
@@ -35491,6 +35585,10 @@ syms_of_xdisp (void)
   x_stretch_cursor_p = 0;
 #endif
 
+  DEFVAR_BOOL ("keep-point-visible", keep_point_visible,
+	       doc: /* Non-nil means to keep the point visible.  */);
+  keep_point_visible = 1;
+
   DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
     doc: /* Non-nil means highlight trailing whitespace.
 The face used for trailing whitespace is `trailing-whitespace'.  */);
-- 
2.33.1


  parent reply	other threads:[~2021-12-04 11:18 UTC|newest]

Thread overview: 111+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <87ilwd7zaq.fsf.ref@yahoo.com>
2021-11-28  3:07 ` Allowing point to be outside the window? Po Lu
2021-11-28  8:03   ` Eli Zaretskii
2021-11-28  8:13     ` Po Lu
2021-11-28  8:41       ` Eli Zaretskii
2021-11-28 12:47         ` Po Lu
2021-11-28 12:58           ` Eli Zaretskii
2021-11-28 13:10             ` Po Lu
2021-11-28 13:44               ` Eli Zaretskii
2021-11-29  1:47                 ` Po Lu
2021-11-29 13:00                   ` Eli Zaretskii
2021-11-29 13:22                     ` Po Lu
2021-11-29 13:43                       ` Eli Zaretskii
2021-11-30  1:40                         ` Po Lu
2021-11-30 16:49                           ` [External] : " Drew Adams
2021-11-30 17:26                             ` Eli Zaretskii
2021-11-30 18:10                               ` Lars Ingebrigtsen
2021-11-30 18:32                                 ` Eli Zaretskii
2021-11-30 18:49                                 ` Stefan Kangas
2021-11-30 19:21                                   ` Eli Zaretskii
2021-11-30 20:57                                     ` Drew Adams
2021-11-30 23:41                                 ` Daniel Martín
2021-12-01  8:30                                   ` martin rudalics
2021-12-01  9:10                                     ` Juri Linkov
2021-11-30 23:20                               ` Stefan Monnier
2021-12-04 11:18                           ` Po Lu [this message]
2021-12-04 12:55                             ` Eli Zaretskii
2021-12-04 13:13                               ` Po Lu
2021-12-04 16:24                                 ` Eli Zaretskii
2021-12-05  0:40                                   ` Po Lu
2021-12-04 17:15                                 ` Eli Zaretskii
2021-12-05  0:45                                   ` Po Lu
2021-12-05  9:03                                     ` Eli Zaretskii
2021-12-06  2:11                                       ` Po Lu
2021-12-06 14:13                                         ` Eli Zaretskii
2021-12-07  2:18                                           ` Po Lu
2021-12-07 13:42                                             ` Eli Zaretskii
2021-12-08  1:17                                               ` Po Lu
2021-12-08 17:14                                                 ` Eli Zaretskii
2021-12-09  0:23                                                   ` Po Lu
2021-12-09  8:02                                                     ` Eli Zaretskii
2021-12-09  9:22                                                       ` Po Lu
2021-12-09 10:02                                                         ` Eli Zaretskii
2021-12-25  6:45                                                       ` Po Lu
2021-12-25  7:07                                                         ` Eli Zaretskii
2022-02-06  7:22                                                         ` Po Lu
2022-02-06 11:34                                                           ` Eli Zaretskii
2022-02-06 11:46                                                             ` Po Lu
2022-02-06 11:55                                                               ` Eli Zaretskii
2022-02-06 12:21                                                                 ` Po Lu
2022-02-06 16:15                                                                   ` Eli Zaretskii
2022-02-07  1:21                                                                     ` Po Lu
2022-02-07  7:21                                                                       ` Po Lu
2022-02-07 13:41                                                                         ` Eli Zaretskii
2022-02-07 13:57                                                                           ` Po Lu
2022-02-07 14:24                                                                             ` Eli Zaretskii
2022-02-08  0:58                                                                               ` Po Lu
2022-02-08 17:08                                                                                 ` Eli Zaretskii
2022-02-09  1:57                                                                                   ` Po Lu
2022-02-10 13:04                                                                                     ` Eli Zaretskii
2022-02-10 13:09                                                                                       ` Po Lu
2021-12-09 11:45                                         ` Eli Zaretskii
2021-12-09 12:19                                           ` Po Lu
2021-12-09 12:45                                             ` Eli Zaretskii
2021-12-04 13:00                             ` dick
2021-12-04 13:14                               ` tomas
2021-12-04 13:19                               ` Po Lu
2021-12-04 13:41                                 ` Eli Zaretskii
2021-12-05  0:46                                   ` Po Lu
2021-12-05  7:12                                     ` Eli Zaretskii
2021-12-05  7:16                                       ` Po Lu
2021-12-05  8:48                                         ` Eli Zaretskii
2021-12-05  9:15                                           ` Po Lu
2021-12-05  9:25                                             ` Eli Zaretskii
2021-12-05  9:31                                               ` Po Lu
2021-12-05 10:34                                                 ` Eli Zaretskii
2021-12-05 10:37                                                   ` Po Lu
2021-12-04 14:17                                 ` dick
2021-12-04 16:33                                   ` Eli Zaretskii
2021-12-04 17:13                                     ` dick
2021-12-05  0:48                                       ` Po Lu
2021-11-28 14:03       ` Alan Mackenzie
2021-11-28 14:28         ` Eric S Fraga
2021-11-28 14:39           ` Eli Zaretskii
2021-11-28 16:55             ` Eric S Fraga
2021-11-28 14:42         ` dick
2021-11-28 15:39         ` Kévin Le Gouguec
2021-11-28 15:45           ` Eli Zaretskii
2021-11-28 17:14             ` Kévin Le Gouguec
2021-11-28 16:59           ` Eric S Fraga
2021-11-28 17:30             ` Kévin Le Gouguec
2021-11-29  0:34             ` Dmitry Gutov
2021-11-29  0:34         ` Po Lu
2021-12-08  1:45           ` John Ankarström
2021-12-08 12:45             ` Eli Zaretskii
2021-12-08 13:33               ` John Ankarström
2021-12-08 13:38                 ` Po Lu
2021-12-08 13:52                   ` John Ankarström
2021-12-08 14:26                 ` Eli Zaretskii
2021-12-08 16:57                   ` Stefan Monnier
2021-12-08 19:29                     ` Yuri Khan
2021-12-09  0:16                     ` Po Lu
2021-12-08 19:21                 ` Rudolf Schlatte
2021-12-08 19:56                   ` Juri Linkov
2021-12-08 20:05                     ` André A. Gomes
2021-12-08 20:31                     ` Linux console scrollback [ Was: Allowing point to be outside the window? ] Alan Mackenzie
2021-12-09  0:17                   ` Allowing point to be outside the window? Po Lu
2021-12-08 22:25                 ` Kévin Le Gouguec
2021-12-08 23:17                   ` John Ankarström
     [not found] <9603C99D-97E7-4285-A1C1-022191B6F5CC@univie.ac.at>
2021-12-08 18:43 ` Konrad Podczeck
2021-12-08 20:47   ` John Ankarström
2021-12-09 15:34 Konrad Podczeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87czmcvcs1.fsf@yahoo.com \
    --to=luangruo@yahoo.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).