emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: More enhancements to fringe bitmaps.


From: Marco Munari
Subject: Re: More enhancements to fringe bitmaps.
Date: Sun, 21 Mar 2004 04:27:29 +0100
User-agent: Gnus/5.110002 (No Gnus v0.2) Emacs/21.3.50 (gnu/linux)

related to previous discussion with Kim and , an updated patch follows

the additional news:
fringe.c: i remove my bitmap redefinition (but i keep change
on default ALIGN of thos bitmap), and i move my bitmaps in a
customizable variable fringe-bitmap-group in fringe.el, which can be
        default nil
        tiny (0)
        small (1)
        medium (2)
all bitmaps valuea are defined in a octal string,
i was in dubt about the name of fringe-bitmap-group, is it fine or it
is better fringe-bitmaps-group or something else?

The fringe/fringe_inactive now react fine istantly when mouse is
moved or another window is selected.

[I'm waiting papers in my address box in Italy, right?]

? mar_emacs_cvs.diff
? mar_emacs_cvs.patch
? lispintro/Makefile.in.cvs6modified
? lispref/display.dvi
Index: etc/TODO
===================================================================
RCS file: /cvsroot/emacs/emacs/etc/TODO,v
retrieving revision 1.62
diff -u -r1.62 TODO
--- etc/TODO    19 Mar 2004 21:10:10 -0000      1.62
+++ etc/TODO    21 Mar 2004 02:53:33 -0000
@@ -63,6 +63,11 @@
 * Remove the limitation that window and frame widths and heights can
   be only full columns/lines.
 
+* Move fringe to be displayed between display margins and text area.
+  [KFS is looking into this].
+
+* Set fringe widths per-window/per-buffer.
+
 Other features we would like:
 
 * Have a command suggestion help system that recognizes patterns
Index: lisp/faces.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/faces.el,v
retrieving revision 1.282
diff -u -r1.282 faces.el
--- lisp/faces.el       27 Feb 2004 17:30:23 -0000      1.282
+++ lisp/faces.el       21 Mar 2004 02:53:36 -0000
@@ -1923,6 +1923,21 @@
   :version "21.1"
   :group 'frames
   :group 'basic-faces)
+;(put 'fringe-active 'face-alias 'fringe) ;deprecated, just to be clare
+
+(defface fringe-inactive
+  '((t
+     :inherit fringe)
+    (((class color) (background light))
+     :background "grey75")
+    (((class color) (background dark))
+     :background "grey30")
+    (t
+     :background "light gray"))
+  "Basic face for the fringes of active input emacs windows."
+  :version "21.4"
+  :group 'frames
+  :group 'basic-faces)
 
 
 (defface scroll-bar '()
Index: lisp/fringe.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/fringe.el,v
retrieving revision 1.11
diff -u -r1.11 fringe.el
--- lisp/fringe.el      15 Mar 2004 07:27:02 -0000      1.11
+++ lisp/fringe.el      21 Mar 2004 02:53:36 -0000
@@ -229,6 +229,199 @@
               0)
            (float (frame-char-width))))
   
+
+; control default fringe group of bitmaps
+
+(defvar fringe-bitmap-group nil)
+(setq fringe-bitmap-group nil) ;orrible, but a way to avoid undefined in 
conditions
+
+(defun set-fringe-bitmap-group (symbol value)
+  "Set frimge-bitmap-group (SYMBOL) to VALUE and put into effect.
+See custom `fringe-bitmap-group' for possible values and their effect."
+  (cond ((eq 0 value)
+        (progn ;string numbers are expressed in \octal or \xhex
+          (define-fringe-bitmap "\4\17\4" nil 4 'center
+            left-truncation-fringe-bitmap)
+          (define-fringe-bitmap "\2\17\2" nil 4 'center
+            right-truncation-fringe-bitmap)
+          (define-fringe-bitmap "\2\7\2\2\2" nil 3 'top
+            up-arrow-fringe-bitmap)
+          (define-fringe-bitmap "\2\2\2\7\2" nil 3 'bottom
+            down-arrow-fringe-bitmap)
+          (define-fringe-bitmap "\6\1\5\6\7" nil 3 'bottom
+            continued-line-fringe-bitmap)
+          (define-fringe-bitmap "\3\4\5\3\7" nil 3 'top
+            continuation-line-fringe-bitmap)
+          (define-fringe-bitmap "\7\4\4" nil 3 'top
+            top-left-angle-fringe-bitmap)
+          (define-fringe-bitmap "\7\1\1" nil 3 'top
+            top-right-angle-fringe-bitmap)
+          (define-fringe-bitmap "\4\4\7" nil 3 'bottom
+            bottom-left-angle-fringe-bitmap)
+          (define-fringe-bitmap "\1\1\7" nil 3 'bottom
+            bottom-right-angle-fringe-bitmap)))
+       ((eq 1 value)
+        (progn
+          (define-fringe-bitmap "\4\10\37\10\4" nil 5 'center
+            left-truncation-fringe-bitmap)
+          (define-fringe-bitmap "\4\2\37\2\4" nil 5 'center
+            right-truncation-fringe-bitmap)
+          (define-fringe-bitmap "\4\16\25\4\4\4" nil 5 'top
+            up-arrow-fringe-bitmap)
+          (define-fringe-bitmap "\4\4\4\25\16\4" nil 5 'bottom
+            down-arrow-fringe-bitmap)
+          (define-fringe-bitmap "\6\1\11\12\14\16" nil 4 'bottom
+            continued-line-fringe-bitmap)
+          (define-fringe-bitmap "\6\10\11\5\3\7" nil 4 'top
+            continuation-line-fringe-bitmap)
+          (define-fringe-bitmap "\17\10\10\10" nil 4 'top
+            top-left-angle-fringe-bitmap)
+          (define-fringe-bitmap "\17\1\1\1" nil 4 'top
+            top-right-angle-fringe-bitmap)
+          (define-fringe-bitmap "\10\10\10\17" nil 4 'bottom
+            bottom-left-angle-fringe-bitmap)
+          (define-fringe-bitmap "\1\1\1\17" nil 4 'bottom
+            bottom-right-angle-fringe-bitmap)))
+       ((eq 2 value)
+        (progn
+          (define-fringe-bitmap "\4\10\20\77\20\10\4" nil 6 'center
+            left-truncation-fringe-bitmap)
+          (define-fringe-bitmap "\10\4\2\77\2\4\10" nil 6 'center
+            right-truncation-fringe-bitmap)
+          (define-fringe-bitmap "\10\34\52\111\10\10" nil 7 'top
+            up-arrow-fringe-bitmap)
+          (define-fringe-bitmap "\10\10\111\52\34\10" nil 7 'bottom
+            down-arrow-fringe-bitmap)
+          (define-fringe-bitmap "\16\1\21\26\34\37" nil 5 'bottom
+            continued-line-fringe-bitmap)
+          (define-fringe-bitmap "\10\20\21\15\7\37" nil 5 'top
+            continuation-line-fringe-bitmap)
+          (define-fringe-bitmap "\37\20\20\20\20" nil 5 'top
+            top-left-angle-fringe-bitmap)
+          (define-fringe-bitmap "\37\1\1\1\1" nil 5 'top
+            top-right-angle-fringe-bitmap)
+          (define-fringe-bitmap "\20\20\20\20\37" nil 5 'bottom
+            bottom-left-angle-fringe-bitmap)
+          (define-fringe-bitmap "\1\1\1\1\37" nil 5 'bottom
+            bottom-right-angle-fringe-bitmap)))
+       ((and (eq nil value)
+             ;;(not (eq fringe-bitmap-group value)) ;how to compare to previous
+             )
+        (progn
+          (destroy-fringe-bitmap left-truncation-fringe-bitmap)
+          (destroy-fringe-bitmap right-truncation-fringe-bitmap)
+          (destroy-fringe-bitmap up-arrow-fringe-bitmap)
+          (destroy-fringe-bitmap down-arrow-fringe-bitmap)
+          (destroy-fringe-bitmap continued-line-fringe-bitmap)
+          (destroy-fringe-bitmap continuation-line-fringe-bitmap)
+          (destroy-fringe-bitmap top-left-angle-fringe-bitmap)
+          (destroy-fringe-bitmap top-right-angle-fringe-bitmap)
+          (destroy-fringe-bitmap bottom-left-angle-fringe-bitmap)
+          (destroy-fringe-bitmap bottom-right-angle-fringe-bitmap)
+          ;(destroy-fringe-bitmap )
+          )))
+  (setq fringe-bitmap-group value)) ;how to use symbol?
+
+;;;###autoload
+(defcustom fringe-bitmap-group nil
+  "*Specify the bitmap set (related to size) of fringe bitmaps
+nil is the default bitpapset (quit big)
+0 (tiny) for smallest bitmap as possible"
+  :type '(choice (const :tag "Default size" nil)
+                (const :tag "tiny" 0)
+                (const :tag "small" 1)
+                (const :tag "medium" 2))
+  :group 'frames
+  :require 'fringe
+  :set 'set-fringe-bitmap-group)
+
+;;The following part close to the end is not well done and not necessary
+;;so commented as it can be removed
+;; (it's an adapted copy/paste from above with few modifications)
+;;the purpose is to have eventually more interactive ways to
+;; customize fringe-bitmap-group
+;;document string are still wrong related to above copy
+;;the idea to be valued -before remove- is to choose fringe-bitmap-group
+;; (which differs principally in size) depending on fringe width.
+;;but in this case i (mar) think it should be moved in fringe.c.
+;
+;(defun fringe-query-bitmap-group (&optional all-frames)
+;  "Query user for fringe bitmap group.
+;Returns values suitable for left-fringe and right-fringe frame parameters.
+;If ALL-FRAMES, the negation of the fringe values in
+;`default-frame-alist' is used when user enters the empty string.
+;Otherwise the negation of the fringe value in the currently selected
+;frame parameter is used."
+;  (let ((mode (intern (completing-read
+;                     "Select fringe bitmap for all frames (type ? for list): "
+;                     '(("default") ("tiny") ("small"))
+;                     nil t))))
+;    (cond ((eq mode 'default) nil)
+;        ((eq mode 'tiny) 0)
+;        ((eq mode 'small) 1)
+;        ((eq mode (intern ""))
+;         (if (> 5 (... cdr (assq 'left-fringe
+;                              (if all-frames
+;                                  default-frame-alist
+;                                (frame-parameters (selected-frame))))))
+;             nil
+;           0)))))
+;
+;;;;###autoload
+;(defun fringe-bitmap-group (&optional mode)
+;  "...Set the default appearance of fringes on all frames.
+;
+;...When called interactively, query the user for MODE.  Valid values
+;for MODE include `none', `default', `left-only', `right-only',
+;`minimal' and `half'.
+;
+;When used in a Lisp program, MODE can be a cons cell where the
+;integer in car specifies the left fringe width and the integer in
+;cdr specifies the right fringe width.  MODE can also be a single
+;integer that specifies both the left and the right fringe width.
+;If a fringe width specification is nil, that means to use the
+;default width (8 pixels).  This command may round up the left and
+;right width specifications to ensure that their sum is a multiple
+;of the character width of a frame.  It never rounds up a fringe
+;width of 0.
+;
+;Fringe widths set by `set-window-fringes' override the default
+;fringe widths set by this command.  This command applies to all
+;frames that exist and frames to be created in the future.  If you
+;want to set the default appearance of fringes on the selected
+;frame only, see the command `set-fringe-style'."
+;  (interactive (list (fringe-query-bitmap-group 'all-frames)))
+;  (set-fringe-bitmap-group nil mode))
+;
+;;;;###autoload
+;(defun set-fringe-style (&optional mode)
+;  "...Set the default appearance of fringes on the selected frame.
+;
+;...When called interactively, query the user for MODE.  Valid values
+;for MODE include `none', `default', `left-only', `right-only',
+;`minimal' and `half'.
+;
+;When used in a Lisp program, MODE can be a cons cell where the
+;integer in car specifies the left fringe width and the integer in
+;cdr specifies the right fringe width.  MODE can also be a single
+;integer that specifies both the left and the right fringe width.
+;If a fringe width specification is nil, that means to use the
+;default width (8 pixels).  This command may round up the left and
+;right width specifications to ensure that their sum is a multiple
+;of the character width of a frame.  It never rounds up a fringe
+;width of 0.
+;
+;Fringe widths set by `set-window-fringes' override the default
+;fringe widths set by this command.  If you want to set the
+;default appearance of fringes on all frames, see the command
+;`fringe-mode'."
+;  (interactive (list (fringe-query-bitmap-group)))
+;  (modify-frame-parameters
+;   (selected-frame)
+;   (list (cons 'left-fringe (if (consp mode) (car mode) mode))
+;       (cons 'right-fringe (if (consp mode) (cdr mode) mode)))))
+;
+
 (provide 'fringe)
 
 ;;; arch-tag: 6611ef60-0869-47ed-8b93-587ee7d3ff5d
Index: lisp/ibuffer.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/ibuffer.el,v
retrieving revision 1.57
diff -u -r1.57 ibuffer.el
--- lisp/ibuffer.el     1 Sep 2003 15:45:12 -0000       1.57
+++ lisp/ibuffer.el     21 Mar 2004 02:53:43 -0000
@@ -199,7 +199,7 @@
   :group 'ibuffer)
 
 (defcustom ibuffer-eliding-string "..."
-  "The string to use for eliding long columns."
+  "The string to use for eliding long lines."
   :type 'string
   :group 'ibuffer)
 
Index: src/dispextern.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/dispextern.h,v
retrieving revision 1.170
diff -u -r1.170 dispextern.h
--- src/dispextern.h    19 Mar 2004 00:42:24 -0000      1.170
+++ src/dispextern.h    21 Mar 2004 02:53:44 -0000
@@ -1171,6 +1171,20 @@
       ? MATRIX_HEADER_LINE_ROW (MATRIX)->height        \
       : 0)
 
+/* Return the fringe mode relative to selected/unselected window,
+   parameters  W the window,  AFFID Active Fringe Face ID          */
+
+#define CURRENT_FRINGE_FACE_ID_2(W,AFFID)                      \
+       (!fringe_in_non_selected_windows                        \
+       || ((W) == XWINDOW (selected_window))           \
+       ? AFFID                                         \
+       : FRINGE_INACTIVE_FACE_ID)
+
+/* see above, FRINGE_FACE_ID is the default */
+
+#define CURRENT_FRINGE_FACE_ID(W)                      \
+       CURRENT_FRINGE_FACE_ID_2(W,FRINGE_FACE_ID)
+
 /* Return the desired face id for the mode line of a window, depending
    on whether the window is selected or not, or if the window is the
    scrolling window for the currently active minibuffer window.
@@ -1518,6 +1532,7 @@
   MODE_LINE_INACTIVE_FACE_ID,
   TOOL_BAR_FACE_ID,
   FRINGE_FACE_ID,
+  FRINGE_INACTIVE_FACE_ID,
   HEADER_LINE_FACE_ID,
   SCROLL_BAR_FACE_ID,
   BORDER_FACE_ID,
@@ -2521,6 +2536,7 @@
 extern Lisp_Object Qtool_bar;
 extern Lisp_Object Vshow_trailing_whitespace;
 extern int mode_line_in_non_selected_windows;
+extern int fringe_in_non_selected_windows;
 extern int redisplaying_p;
 extern Lisp_Object Vimage_types;
 extern void add_to_log P_ ((char *, Lisp_Object, Lisp_Object));
Index: src/fringe.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/fringe.c,v
retrieving revision 1.10
diff -u -r1.10 fringe.c
--- src/fringe.c        1 Mar 2004 23:56:44 -0000       1.10
+++ src/fringe.c        21 Mar 2004 02:53:45 -0000
@@ -413,13 +413,14 @@
 struct fringe_bitmap standard_bitmaps[MAX_STANDARD_FRINGE_BITMAPS] =
 {
   { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
+  /*      bits, height,           width,period,   align   , dynamic*/
   { FRBITS (unknown_bits),            8, 0, ALIGN_BITMAP_CENTER, 0 },
   { FRBITS (left_arrow_bits),         8, 0, ALIGN_BITMAP_CENTER, 0 },
   { FRBITS (right_arrow_bits),        8, 0, ALIGN_BITMAP_CENTER, 0 },
   { FRBITS (up_arrow_bits),           8, 0, ALIGN_BITMAP_TOP,    0 },
   { FRBITS (down_arrow_bits),         8, 0, ALIGN_BITMAP_BOTTOM, 0 },
-  { FRBITS (continued_bits),          8, 0, ALIGN_BITMAP_CENTER, 0 },
-  { FRBITS (continuation_bits),       8, 0, ALIGN_BITMAP_CENTER, 0 },
+  { FRBITS (continued_bits),          8, 0, ALIGN_BITMAP_BOTTOM, 0 },
+  { FRBITS (continuation_bits),       8, 0, ALIGN_BITMAP_TOP,    0 },
   { FRBITS (ov_bits),                 8, 0, ALIGN_BITMAP_CENTER, 0 },
   { FRBITS (top_left_angle_bits),     8, 0, ALIGN_BITMAP_TOP,    0 },
   { FRBITS (top_right_angle_bits),    8, 0, ALIGN_BITMAP_TOP,    0 },
@@ -478,20 +479,21 @@
 
   if (which != NO_FRINGE_BITMAP)
     {
+      face_id = CURRENT_FRINGE_FACE_ID(w);
     }
   else if (left_p)
     {
       which = row->left_fringe_bitmap;
-      face_id = row->left_fringe_face_id;
+      face_id = CURRENT_FRINGE_FACE_ID_2(w, row->left_fringe_face_id);
     }
   else
     {
       which = row->right_fringe_bitmap;
-      face_id = row->right_fringe_face_id;
+      face_id = CURRENT_FRINGE_FACE_ID_2(w, row->right_fringe_face_id);
     }
 
   if (face_id == DEFAULT_FACE_ID)
-    face_id = fringe_faces[which];
+    face_id = CURRENT_FRINGE_FACE_ID_2(w, fringe_faces[which]);
 
   fb = fringe_bitmaps[which];
   if (fb == NULL)
@@ -800,7 +802,8 @@
       else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
        {
          left = row->left_user_fringe_bitmap;
-         left_face_id = row->left_user_fringe_face_id;
+         left_face_id =
+           CURRENT_FRINGE_FACE_ID_2(w,row->left_user_fringe_face_id);
        }
       else if (row->indicate_bob_p && boundary_pos <= 0)
        left = ((row->indicate_eob_p && boundary_pos < 0)
@@ -826,7 +829,8 @@
       else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
        {
          right = row->right_user_fringe_bitmap;
-         right_face_id = row->right_user_fringe_face_id;
+         right_face_id =
+           CURRENT_FRINGE_FACE_ID_2(w,row->right_user_fringe_face_id);
        }
       else if (row->indicate_bob_p && boundary_pos > 0)
        right = ((row->indicate_eob_p && boundary_pos >= 0)
@@ -860,8 +864,8 @@
          redraw_p = row->redraw_fringe_bitmaps_p = 
cur->redraw_fringe_bitmaps_p = 1;
          cur->left_fringe_bitmap = left;
          cur->right_fringe_bitmap = right;
-         cur->left_fringe_face_id = left_face_id;
-         cur->right_fringe_face_id = right_face_id;
+         cur->left_fringe_face_id = CURRENT_FRINGE_FACE_ID_2(w,left_face_id);
+         cur->right_fringe_face_id = CURRENT_FRINGE_FACE_ID_2(w,right_face_id);
        }
 
       if (row->overlay_arrow_p != cur->overlay_arrow_p)
@@ -872,8 +876,8 @@
 
       row->left_fringe_bitmap = left;
       row->right_fringe_bitmap = right;
-      row->left_fringe_face_id = left_face_id;
-      row->right_fringe_face_id = right_face_id;
+      row->left_fringe_face_id = CURRENT_FRINGE_FACE_ID_2(w,left_face_id);
+      row->right_fringe_face_id = CURRENT_FRINGE_FACE_ID_2(w,right_face_id);
     }
 
   return redraw_p;
Index: src/window.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/window.c,v
retrieving revision 1.462
diff -u -r1.462 window.c
--- src/window.c        4 Mar 2004 17:16:23 -0000       1.462
+++ src/window.c        21 Mar 2004 02:53:51 -0000
@@ -129,6 +129,10 @@
    minibuffer is active.  */
 int mode_line_in_non_selected_windows;
 
+/* Non-zero means to use fringe-inactive face in all windows but the
+   selected-window.  */
+int fringe_in_non_selected_windows;
+
 /* If a window gets smaller than either of these, it is removed. */
 
 EMACS_INT window_min_height;
@@ -1775,8 +1779,10 @@
     window = Fnext_window (window, Qnil, all_frames);
   for (; i < 0; ++i)
     window = Fprevious_window (window, Qnil, all_frames);
-
-  Fselect_window (window, Qnil);
+  if (window != selected_window) {
+    //selected_window->circa row->redraw_fringe_bitmaps_p = 1;
+    Fselect_window (window, Qnil);
+  }
   return Qnil;
 }
 
@@ -6475,6 +6481,10 @@
 If the minibuffer is active, the `minibuffer-scroll-window' mode line
 is displayed in the `mode-line' face.  */);
   mode_line_in_non_selected_windows = 1;
+
+  DEFVAR_BOOL ("fringe-in-non-selected-windows", 
&fringe_in_non_selected_windows,
+              doc: /* Non-nil means to use `fringe-inactive' face in 
non-selected windows.  */);
+  fringe_in_non_selected_windows = 1;
 
   DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
               doc: /* If non-nil, this is a buffer and \\[scroll-other-window] 
should scroll its window.  */);
Index: src/xfaces.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xfaces.c,v
retrieving revision 1.289
diff -u -r1.289 xfaces.c
--- src/xfaces.c        9 Feb 2004 15:39:49 -0000       1.289
+++ src/xfaces.c        21 Mar 2004 02:53:57 -0000
@@ -322,7 +322,7 @@
 
 /* Names of basic faces.  */
 
-Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe;
+Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe, Qfringe_inactive;
 Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
 Lisp_Object Qmode_line_inactive;
 extern Lisp_Object Qmode_line;
@@ -6626,6 +6626,7 @@
       realize_named_face (f, Qmode_line_inactive, MODE_LINE_INACTIVE_FACE_ID);
       realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
       realize_named_face (f, Qfringe, FRINGE_FACE_ID);
+      realize_named_face (f, Qfringe_inactive, FRINGE_INACTIVE_FACE_ID);
       realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
       realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
       realize_named_face (f, Qborder, BORDER_FACE_ID);
@@ -7701,6 +7702,8 @@
   staticpro (&Qregion);
   Qfringe = intern ("fringe");
   staticpro (&Qfringe);
+  Qfringe_inactive = intern ("fringe-inactive");
+  staticpro (&Qfringe_inactive);
   Qheader_line = intern ("header-line");
   staticpro (&Qheader_line);
   Qscroll_bar = intern ("scroll-bar");
Saluti,
MARco
-- 
x(t),y(t) = th(3t-34.5)*e^[-(3t-34.5)^2]/2-4.3+e^(-1.8/t^2)/(.8*atg(t-
3)+2)(t-1.8)-.3th(5t-42.5),(1.4e^[-(3t-34.5)^2]+1-sgn[|t-8.5|-.5]*1.5*
|sin(pi*t)|^[2e^(-(t-11.5)^2)+.5+e^(-(.6t-3.3)^2)])/(.5+t)+1  ; 0<t<14

reply via email to

[Prev in Thread] Current Thread [Next in Thread]