root/src/fringe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lookup_fringe_bitmap
  2. get_fringe_bitmap_name
  3. get_fringe_bitmap_data
  4. draw_fringe_bitmap_1
  5. get_logical_cursor_bitmap
  6. get_logical_fringe_bitmap
  7. draw_fringe_bitmap
  8. draw_row_fringe_bitmaps
  9. draw_window_fringes
  10. update_window_fringes
  11. destroy_fringe_bitmap
  12. DEFUN
  13. init_fringe_bitmap
  14. syms_of_fringe
  15. mark_fringe_data
  16. init_fringe_once
  17. init_fringe_once_for_pdumper
  18. init_fringe
  19. gui_init_fringe
  20. gui_define_fringe_bitmap
  21. w32_reset_fringes

     1 /* Fringe handling (split from xdisp.c).
     2    Copyright (C) 1985-1988, 1993-1995, 1997-2023 Free Software
     3    Foundation, Inc.
     4 
     5 This file is part of GNU Emacs.
     6 
     7 GNU Emacs is free software: you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation, either version 3 of the License, or (at
    10 your option) any later version.
    11 
    12 GNU Emacs is distributed in the hope that it will be useful,
    13 but WITHOUT ANY WARRANTY; without even the implied warranty of
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15 GNU General Public License for more details.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    19 
    20 #include <config.h>
    21 
    22 #include <byteswap.h>
    23 
    24 #include "lisp.h"
    25 #include "frame.h"
    26 #include "window.h"
    27 #include "dispextern.h"
    28 #include "buffer.h"
    29 #include "blockinput.h"
    30 #include "termhooks.h"
    31 #include "pdumper.h"
    32 
    33 #ifdef HAVE_PGTK
    34 # include "pgtkterm.h"
    35 #endif
    36 
    37 /* Fringe bitmaps are represented in three different ways:
    38 
    39    Logical bitmaps are used internally to denote things like
    40    'end-of-buffer', 'left-truncation', 'overlay-arrow', etc.
    41 
    42    Physical bitmaps specify the visual appearance of the bitmap,
    43    e.g. 'bottom-left-angle', 'left-arrow', 'left-triangle', etc.
    44    User defined bitmaps are physical bitmaps.
    45 
    46    Internally, fringe bitmaps for a specific display row are
    47    represented as a simple integer that is used as an index
    48    into the table of all defined bitmaps.  This index is stored
    49    in the `fringe' property of the physical bitmap symbol.
    50 
    51    Logical bitmaps are mapped to physical bitmaps through the
    52    buffer-local `fringe-indicator-alist' variable.
    53 
    54    Each element of this alist is a cons (LOGICAL . PHYSICAL)
    55    mapping a logical bitmap to a physical bitmap.
    56    PHYSICAL is either a symbol to use in both left and right fringe,
    57    or a cons of two symbols (LEFT . RIGHT) denoting different
    58    bitmaps to use in left and right fringe.
    59 
    60    LOGICAL is first looked up in the window's buffer's buffer-local
    61    value of the fringe-indicator-alist variable, and if not present,
    62    in the global value of fringe-indicator-alist.
    63 
    64    If LOGICAL is not present in either alist, or the PHYSICAL value
    65    found is nil, no bitmap is shown for the logical bitmap.
    66 
    67    The `left-fringe' and `right-fringe' display properties
    68    must specify physical bitmap symbols.
    69 */
    70 
    71 enum fringe_bitmap_align
    72 {
    73   ALIGN_BITMAP_CENTER = 0,
    74   ALIGN_BITMAP_TOP,
    75   ALIGN_BITMAP_BOTTOM
    76 };
    77 
    78 struct fringe_bitmap
    79 {
    80   unsigned short *bits;
    81   unsigned height : 8;
    82   unsigned width : 8;
    83   unsigned period : 8;
    84   unsigned align : 2;
    85   bool_bf dynamic : 1;
    86 };
    87 
    88 
    89 /***********************************************************************
    90                                Fringe bitmaps
    91  ***********************************************************************/
    92 
    93 /* Undefined bitmap.  A question mark.  */
    94 /*
    95   ..xxxx..
    96   .xxxxxx.
    97   xx....xx
    98   xx....xx
    99   ....xx..
   100   ...xx...
   101   ...xx...
   102   ........
   103   ...xx...
   104   ...xx...
   105 */
   106 static unsigned short question_mark_bits[] = {
   107   0x3c, 0x7e, 0xc3, 0xc3, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
   108 
   109 /* An exclamation mark.  */
   110 /*
   111   ...XX...
   112   ...XX...
   113   ...XX...
   114   ...XX...
   115   ...XX...
   116   ...XX...
   117   ...XX...
   118   ........
   119   ...XX...
   120   ...XX...
   121 */
   122 static unsigned short exclamation_mark_bits[] = {
   123   0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18};
   124 
   125 /* An arrow like this: `<-'.  */
   126 /*
   127   ...xx...
   128   ..xx....
   129   .xx.....
   130   xxxxxx..
   131   xxxxxx..
   132   .xx.....
   133   ..xx....
   134   ...xx...
   135 */
   136 static unsigned short left_arrow_bits[] = {
   137    0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
   138 
   139 
   140 /* Right truncation arrow bitmap `->'.  */
   141 /*
   142   ...xx...
   143   ....xx..
   144   .....xx.
   145   ..xxxxxx
   146   ..xxxxxx
   147   .....xx.
   148   ....xx..
   149   ...xx...
   150 */
   151 static unsigned short right_arrow_bits[] = {
   152    0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
   153 
   154 
   155 /* Up arrow bitmap.  */
   156 /*
   157   ...xx...
   158   ..xxxx..
   159   .xxxxxx.
   160   xxxxxxxx
   161   ...xx...
   162   ...xx...
   163   ...xx...
   164   ...xx...
   165 */
   166 static unsigned short up_arrow_bits[] = {
   167    0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
   168 
   169 
   170 /* Down arrow bitmap.  */
   171 /*
   172   ...xx...
   173   ...xx...
   174   ...xx...
   175   ...xx...
   176   xxxxxxxx
   177   .xxxxxx.
   178   ..xxxx..
   179   ...xx...
   180 */
   181 static unsigned short down_arrow_bits[] = {
   182    0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
   183 
   184 /* Marker for continuation lines.  */
   185 /*
   186   ..xxxx..
   187   .xxxxx..
   188   xx......
   189   xxx..x..
   190   xxxxxx..
   191   .xxxxx..
   192   ..xxxx..
   193   .xxxxx..
   194 */
   195 static unsigned short left_curly_arrow_bits[] = {
   196    0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
   197 
   198 /* Marker for continued lines.  */
   199 /*
   200   ..xxxx..
   201   ..xxxxx.
   202   ......xx
   203   ..x..xxx
   204   ..xxxxxx
   205   ..xxxxx.
   206   ..xxxx..
   207   ..xxxxx.
   208 */
   209 static unsigned short right_curly_arrow_bits[] = {
   210    0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
   211 
   212 /* Large circle bitmap.  */
   213 /*
   214   ..xxxx..
   215   .xxxxxx.
   216   xxxxxxxx
   217   xxxxxxxx
   218   xxxxxxxx
   219   xxxxxxxx
   220   .xxxxxx.
   221   ..xxxx..
   222 */
   223 static unsigned short large_circle_bits[] = {
   224   0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c};
   225 
   226 /* Reverse Overlay arrow bitmap.  A triangular arrow.  */
   227 /*
   228   ......xx
   229   ....xxxx
   230   ...xxxxx
   231   ..xxxxxx
   232   ..xxxxxx
   233   ...xxxxx
   234   ....xxxx
   235   ......xx
   236 */
   237 static unsigned short left_triangle_bits[] = {
   238    0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
   239 
   240 /* Overlay arrow bitmap.  A triangular arrow.  */
   241 /*
   242   xx......
   243   xxxx....
   244   xxxxx...
   245   xxxxxx..
   246   xxxxxx..
   247   xxxxx...
   248   xxxx....
   249   xx......
   250 */
   251 static unsigned short right_triangle_bits[] = {
   252    0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
   253 
   254 /* First line bitmap.  An top-left angle.  */
   255 /*
   256   xxxxxx..
   257   xxxxxx..
   258   xx......
   259   xx......
   260   xx......
   261   xx......
   262   xx......
   263   ........
   264 */
   265 static unsigned short top_left_angle_bits[] = {
   266    0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
   267 
   268 /* First line bitmap.  An right-up angle.  */
   269 /*
   270   ..xxxxxx
   271   ..xxxxxx
   272   ......xx
   273   ......xx
   274   ......xx
   275   ......xx
   276   ......xx
   277   ........
   278 */
   279 static unsigned short top_right_angle_bits[] = {
   280    0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
   281 
   282 /* Last line bitmap.  An left-down angle.  */
   283 /*
   284   ........
   285   xx......
   286   xx......
   287   xx......
   288   xx......
   289   xx......
   290   xxxxxx..
   291   xxxxxx..
   292 */
   293 static unsigned short bottom_left_angle_bits[] = {
   294    0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
   295 
   296 /* Last line bitmap.  An right-down angle.  */
   297 /*
   298   ........
   299   ......xx
   300   ......xx
   301   ......xx
   302   ......xx
   303   ......xx
   304   ..xxxxxx
   305   ..xxxxxx
   306 */
   307 static unsigned short bottom_right_angle_bits[] = {
   308    0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
   309 
   310 /* First/last line bitmap.  An left bracket.  */
   311 /*
   312   xxxxxx..
   313   xxxxxx..
   314   xx......
   315   xx......
   316   xx......
   317   xx......
   318   xx......
   319   xx......
   320   xxxxxx..
   321   xxxxxx..
   322 */
   323 static unsigned short left_bracket_bits[] = {
   324    0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
   325 
   326 /* First/last line bitmap.  An right bracket.  */
   327 /*
   328   ..xxxxxx
   329   ..xxxxxx
   330   ......xx
   331   ......xx
   332   ......xx
   333   ......xx
   334   ......xx
   335   ......xx
   336   ..xxxxxx
   337   ..xxxxxx
   338 */
   339 static unsigned short right_bracket_bits[] = {
   340   0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
   341 
   342 /* Filled box cursor bitmap.  A filled box; max 13 pixels high.  */
   343 /*
   344   xxxxxxx.
   345   xxxxxxx.
   346   xxxxxxx.
   347   xxxxxxx.
   348   xxxxxxx.
   349   xxxxxxx.
   350   xxxxxxx.
   351   xxxxxxx.
   352   xxxxxxx.
   353   xxxxxxx.
   354   xxxxxxx.
   355   xxxxxxx.
   356   xxxxxxx.
   357 */
   358 static unsigned short filled_rectangle_bits[] = {
   359    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
   360 
   361 /* Hollow box cursor bitmap.  A hollow box; max 13 pixels high.  */
   362 /*
   363   xxxxxxx.
   364   x.....x.
   365   x.....x.
   366   x.....x.
   367   x.....x.
   368   x.....x.
   369   x.....x.
   370   x.....x.
   371   x.....x.
   372   x.....x.
   373   x.....x.
   374   x.....x.
   375   xxxxxxx.
   376 */
   377 static unsigned short hollow_rectangle_bits[] = {
   378    0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
   379 
   380 /* Hollow square bitmap.  */
   381 /*
   382   .xxxxxx.
   383   .x....x.
   384   .x....x.
   385   .x....x.
   386   .x....x.
   387   .xxxxxx.
   388 */
   389 static unsigned short hollow_square_bits[] = {
   390    0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
   391 
   392 /* Filled square bitmap.  */
   393 /*
   394   .xxxxxx.
   395   .xxxxxx.
   396   .xxxxxx.
   397   .xxxxxx.
   398   .xxxxxx.
   399   .xxxxxx.
   400 */
   401 static unsigned short filled_square_bits[] = {
   402    0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e};
   403 
   404 /* Bar cursor bitmap.  A vertical bar; max 13 pixels high.  */
   405 /*
   406   xx......
   407   xx......
   408   xx......
   409   xx......
   410   xx......
   411   xx......
   412   xx......
   413   xx......
   414   xx......
   415   xx......
   416   xx......
   417   xx......
   418   xx......
   419 */
   420 static unsigned short vertical_bar_bits[] = {
   421    0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
   422 
   423 /* HBar cursor bitmap.  A horizontal bar; 2 pixels high.  */
   424 /*
   425   xxxxxxx.
   426   xxxxxxx.
   427 */
   428 static unsigned short horizontal_bar_bits[] = {
   429   0xfe, 0xfe};
   430 
   431 
   432 /* Bitmap drawn to indicate lines not displaying text if
   433    `indicate-empty-lines' is non-nil.  */
   434 /*
   435   ........
   436   ..xxxx..
   437   ........
   438   ........
   439   ..xxxx..
   440   ........
   441 */
   442 static unsigned short empty_line_bits[] = {
   443   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   444   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   445   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   446   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   447   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   448   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   449   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
   450   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
   451 
   452 
   453 #define BYTES_PER_BITMAP_ROW  (sizeof (unsigned short))
   454 #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
   455 #define FRBITS(bits)  bits, STANDARD_BITMAP_HEIGHT (bits)
   456 
   457 /* NOTE:  The order of these bitmaps must match the sequence
   458    used in fringe.el to define the corresponding symbols.  */
   459 
   460 static struct fringe_bitmap standard_bitmaps[] =
   461 {
   462   { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
   463   { FRBITS (question_mark_bits),      8, 0, ALIGN_BITMAP_CENTER, 0 },
   464   { FRBITS (exclamation_mark_bits),   8, 0, ALIGN_BITMAP_CENTER, 0 },
   465   { FRBITS (left_arrow_bits),         8, 0, ALIGN_BITMAP_CENTER, 0 },
   466   { FRBITS (right_arrow_bits),        8, 0, ALIGN_BITMAP_CENTER, 0 },
   467   { FRBITS (up_arrow_bits),           8, 0, ALIGN_BITMAP_TOP,    0 },
   468   { FRBITS (down_arrow_bits),         8, 0, ALIGN_BITMAP_BOTTOM, 0 },
   469   { FRBITS (left_curly_arrow_bits),   8, 0, ALIGN_BITMAP_CENTER, 0 },
   470   { FRBITS (right_curly_arrow_bits),  8, 0, ALIGN_BITMAP_CENTER, 0 },
   471   { FRBITS (large_circle_bits),       8, 0, ALIGN_BITMAP_CENTER, 0 },
   472   { FRBITS (left_triangle_bits),      8, 0, ALIGN_BITMAP_CENTER, 0 },
   473   { FRBITS (right_triangle_bits),     8, 0, ALIGN_BITMAP_CENTER, 0 },
   474   { FRBITS (top_left_angle_bits),     8, 0, ALIGN_BITMAP_TOP,    0 },
   475   { FRBITS (top_right_angle_bits),    8, 0, ALIGN_BITMAP_TOP,    0 },
   476   { FRBITS (bottom_left_angle_bits),  8, 0, ALIGN_BITMAP_BOTTOM, 0 },
   477   { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
   478   { FRBITS (left_bracket_bits),       8, 0, ALIGN_BITMAP_CENTER, 0 },
   479   { FRBITS (right_bracket_bits),      8, 0, ALIGN_BITMAP_CENTER, 0 },
   480   { FRBITS (filled_rectangle_bits),   8, 0, ALIGN_BITMAP_CENTER, 0 },
   481   { FRBITS (hollow_rectangle_bits),   8, 0, ALIGN_BITMAP_CENTER, 0 },
   482   { FRBITS (filled_square_bits),      8, 0, ALIGN_BITMAP_CENTER, 0 },
   483   { FRBITS (hollow_square_bits),      8, 0, ALIGN_BITMAP_CENTER, 0 },
   484   { FRBITS (vertical_bar_bits),       8, 0, ALIGN_BITMAP_CENTER, 0 },
   485   { FRBITS (horizontal_bar_bits),     8, 0, ALIGN_BITMAP_BOTTOM, 0 },
   486   { FRBITS (empty_line_bits),         8, 3, ALIGN_BITMAP_TOP,    0 },
   487 };
   488 
   489 #define NO_FRINGE_BITMAP 0
   490 #define UNDEF_FRINGE_BITMAP 1
   491 #define MAX_STANDARD_FRINGE_BITMAPS ARRAYELTS (standard_bitmaps)
   492 
   493 static struct fringe_bitmap **fringe_bitmaps;
   494 static Lisp_Object *fringe_faces;
   495 static int max_fringe_bitmaps;
   496 
   497 int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
   498 
   499 
   500 /* Lookup bitmap number for symbol BITMAP.
   501    Return 0 if not a bitmap.  */
   502 
   503 int
   504 lookup_fringe_bitmap (Lisp_Object bitmap)
   505 {
   506   EMACS_INT bn;
   507 
   508   bitmap = Fget (bitmap, Qfringe);
   509   if (!FIXNUMP (bitmap))
   510     return 0;
   511 
   512   bn = XFIXNUM (bitmap);
   513   if (bn > NO_FRINGE_BITMAP
   514       && bn < max_used_fringe_bitmap
   515       && (bn < MAX_STANDARD_FRINGE_BITMAPS
   516           || fringe_bitmaps[bn] != NULL))
   517     return bn;
   518 
   519   return 0;
   520 }
   521 
   522 /* Get fringe bitmap name for bitmap number BN.
   523 
   524    Found by traversing Vfringe_bitmaps comparing BN to the
   525    fringe property for each symbol.
   526 
   527    Return BN if not found in Vfringe_bitmaps.  */
   528 
   529 static Lisp_Object
   530 get_fringe_bitmap_name (int bn)
   531 {
   532   Lisp_Object bitmaps;
   533   Lisp_Object num;
   534 
   535   /* Zero means no bitmap -- return nil.  */
   536   if (bn <= 0)
   537     return Qnil;
   538 
   539   bitmaps = Vfringe_bitmaps;
   540   num = make_fixnum (bn);
   541 
   542   while (CONSP (bitmaps))
   543     {
   544       Lisp_Object bitmap = XCAR (bitmaps);
   545       if (EQ (num, Fget (bitmap, Qfringe)))
   546         return bitmap;
   547       bitmaps = XCDR (bitmaps);
   548     }
   549 
   550   return num;
   551 }
   552 
   553 /* Get fringe bitmap data for bitmap number BN.  */
   554 
   555 static struct fringe_bitmap *
   556 get_fringe_bitmap_data (int bn)
   557 {
   558   struct fringe_bitmap *fb;
   559 
   560   fb = fringe_bitmaps[bn];
   561   if (fb == NULL)
   562     fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
   563                            ? bn : UNDEF_FRINGE_BITMAP];
   564 
   565   return fb;
   566 }
   567 
   568 /* Draw the bitmap WHICH in one of the left or right fringes of
   569    window W.  ROW is the glyph row for which to display the bitmap; it
   570    determines the vertical position at which the bitmap has to be
   571    drawn.
   572    LEFT_P is 1 for left fringe, 0 for right fringe.
   573 */
   574 
   575 static void
   576 draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which)
   577 {
   578   struct frame *f = XFRAME (WINDOW_FRAME (w));
   579   struct draw_fringe_bitmap_params p;
   580   struct fringe_bitmap *fb;
   581   int period;
   582   int face_id = DEFAULT_FACE_ID;
   583   int offset, header_line_height;
   584 
   585   p.overlay_p = (overlay & 1) == 1;
   586   p.cursor_p = (overlay & 2) == 2;
   587 
   588   if (which != NO_FRINGE_BITMAP)
   589     {
   590       offset = 0;
   591     }
   592   else if (left_p)
   593     {
   594       which = row->left_fringe_bitmap;
   595       face_id = row->left_fringe_face_id;
   596       offset = row->left_fringe_offset;
   597     }
   598   else
   599     {
   600       which = row->right_fringe_bitmap;
   601       face_id = row->right_fringe_face_id;
   602       offset = row->right_fringe_offset;
   603     }
   604 
   605   if (face_id == DEFAULT_FACE_ID)
   606     {
   607       Lisp_Object face = fringe_faces[which];
   608       face_id = NILP (face) ? lookup_named_face (w, f, Qfringe, false)
   609         : lookup_derived_face (w, f, face, FRINGE_FACE_ID, 0);
   610       if (face_id < 0)
   611         face_id = FRINGE_FACE_ID;
   612     }
   613 
   614   fb = get_fringe_bitmap_data (which);
   615 
   616   period = fb->period;
   617 
   618   /* Convert row to frame coordinates.  */
   619   p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;
   620 
   621   p.which = which;
   622   p.bits = fb->bits;
   623   p.wd = fb->width;
   624 
   625   p.h = fb->height;
   626   p.dh = (period > 0 ? (p.y % period) : 0);
   627   p.h -= p.dh;
   628 
   629   /* Adjust y to the offset in the row to start drawing the bitmap.  */
   630   switch (fb->align)
   631     {
   632     case ALIGN_BITMAP_CENTER:
   633       p.y += (row->height - p.h) / 2;
   634       break;
   635     case ALIGN_BITMAP_BOTTOM:
   636       p.y += (row->visible_height - p.h);
   637       break;
   638     case ALIGN_BITMAP_TOP:
   639       break;
   640     }
   641 
   642   p.face = FACE_FROM_ID_OR_NULL (f, face_id);
   643   if (p.face == NULL)
   644     {
   645       /* This could happen after clearing face cache.
   646          But it shouldn't happen anymore.  ++kfs */
   647       return;
   648     }
   649 
   650   prepare_face_for_display (f, p.face);
   651 
   652   /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
   653      the fringe.  */
   654   p.bx = -1;
   655   header_line_height = WINDOW_TAB_LINE_HEIGHT (w)
   656                        + WINDOW_HEADER_LINE_HEIGHT (w);
   657   p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
   658   p.ny = row->visible_height;
   659   if (left_p)
   660     {
   661       int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
   662       int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
   663                                    ? LEFT_MARGIN_AREA
   664                                    : TEXT_AREA));
   665       if (p.wd > wd)
   666         p.wd = wd;
   667       p.x = x - p.wd - (wd - p.wd) / 2;
   668 
   669       if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
   670         {
   671           /* If W has a vertical border to its left, don't draw over it.  */
   672           wd -= ((!WINDOW_LEFTMOST_P (w)
   673                   /* This could be wrong when we allow window local
   674                      right dividers - but the window on the left is hard
   675                      to get.  */
   676                   && !FRAME_RIGHT_DIVIDER_WIDTH (f)
   677                   && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
   678                   /* But don't reduce the fringe width if the window
   679                      has a left margin, because that means we are not
   680                      in danger of drawing over the vertical border,
   681                      and OTOH leaving out that one pixel leaves behind
   682                      traces of the cursor, if it was in column zero
   683                      before drawing non-empty margin area.  */
   684                   && w->left_margin_cols == 0)
   685                  ? 1 : 0);
   686           p.bx = x - wd;
   687           p.nx = wd;
   688         }
   689     }
   690   else
   691     {
   692       int x = window_box_right (w,
   693                                 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
   694                                  ? RIGHT_MARGIN_AREA
   695                                  : TEXT_AREA));
   696       int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
   697       if (p.wd > wd)
   698         p.wd = wd;
   699       p.x = x + (wd - p.wd) / 2;
   700       /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
   701          the fringe.  */
   702       if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
   703         {
   704           p.bx = x;
   705           p.nx = wd;
   706         }
   707     }
   708 
   709   if (p.x >= WINDOW_BOX_LEFT_EDGE_X (w)
   710       && (p.x + p.wd) <= WINDOW_BOX_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w))
   711     FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
   712 }
   713 
   714 static int
   715 get_logical_cursor_bitmap (struct window *w, Lisp_Object cursor)
   716 {
   717   Lisp_Object cmap, bm = Qnil;
   718 
   719   if ((cmap = BVAR (XBUFFER (w->contents), fringe_cursor_alist)), !NILP (cmap))
   720     {
   721       bm = Fassq (cursor, cmap);
   722       if (CONSP (bm))
   723         {
   724           if ((bm = XCDR (bm)), NILP (bm))
   725             return NO_FRINGE_BITMAP;
   726           return lookup_fringe_bitmap (bm);
   727         }
   728     }
   729   if (EQ (cmap, BVAR (&buffer_defaults, fringe_cursor_alist)))
   730     return NO_FRINGE_BITMAP;
   731   bm = Fassq (cursor, BVAR (&buffer_defaults, fringe_cursor_alist));
   732   if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm)))
   733     return NO_FRINGE_BITMAP;
   734   return lookup_fringe_bitmap (bm);
   735 }
   736 
   737 static int
   738 get_logical_fringe_bitmap (struct window *w, Lisp_Object bitmap, int right_p, int partial_p)
   739 {
   740   Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm;
   741   ptrdiff_t ln1 = 0, ln2 = 0;
   742   int ix1 = right_p;
   743   int ix2 = ix1 + (partial_p ? 2 : 0);
   744 
   745   /* Lookup in buffer-local fringe-indicator-alist before global alist.
   746 
   747      Elements are:
   748         BITMAP          -- use for all
   749         (L R)           -- use for left right (whether partial or not)
   750         (L R PL PR)     -- use for left right partial-left partial-right
   751         If any value in local binding is not present or t, use global value.
   752 
   753      If partial, lookup partial bitmap in default value if not found here.
   754      If not partial, or no partial spec is present, use non-partial bitmap.  */
   755 
   756   if ((cmap = BVAR (XBUFFER (w->contents), fringe_indicator_alist)), !NILP (cmap))
   757     {
   758       bm1 = Fassq (bitmap, cmap);
   759       if (CONSP (bm1))
   760         {
   761           if ((bm1 = XCDR (bm1)), NILP (bm1))
   762             return NO_FRINGE_BITMAP;
   763           if (CONSP (bm1))
   764             {
   765               ln1 = list_length (bm1);
   766               if (partial_p)
   767                 {
   768                   if (ln1 > ix2)
   769                     {
   770                       bm = Fnth (make_fixnum (ix2), bm1);
   771                       if (!EQ (bm, Qt))
   772                         goto found;
   773                     }
   774                 }
   775               else
   776                 {
   777                   if (ln1 > ix1)
   778                     {
   779                       bm = Fnth (make_fixnum (ix1), bm1);
   780                       if (!EQ (bm, Qt))
   781                         goto found;
   782                     }
   783                 }
   784             }
   785           else if ((bm = bm1, !EQ (bm, Qt)))
   786             goto found;
   787         }
   788     }
   789 
   790   if (!EQ (cmap, BVAR (&buffer_defaults, fringe_indicator_alist))
   791       && !NILP (BVAR (&buffer_defaults, fringe_indicator_alist)))
   792     {
   793       bm2 = Fassq (bitmap, BVAR (&buffer_defaults, fringe_indicator_alist));
   794       if (CONSP (bm2))
   795         {
   796           if ((bm2 = XCDR (bm2)), !NILP (bm2))
   797             {
   798               if (CONSP (bm2))
   799                 {
   800                   ln2 = list_length (bm2);
   801                   if (partial_p)
   802                     {
   803                       if (ln2 > ix2)
   804                         {
   805                           bm = Fnth (make_fixnum (ix2), bm2);
   806                           if (!EQ (bm, Qt))
   807                             goto found;
   808                         }
   809                     }
   810                 }
   811             }
   812         }
   813     }
   814 
   815   if (ln1 > ix1)
   816     {
   817       bm = Fnth (make_fixnum (ix1), bm1);
   818       if (!EQ (bm, Qt))
   819         goto found;
   820     }
   821 
   822   if (ln2 > ix1)
   823     {
   824       bm = Fnth (make_fixnum (ix1), bm2);
   825       if (!EQ (bm, Qt))
   826         goto found;
   827       return NO_FRINGE_BITMAP;
   828     }
   829   else if ((bm = bm2, NILP (bm)))
   830     return NO_FRINGE_BITMAP;
   831 
   832  found:
   833   return lookup_fringe_bitmap (bm);
   834 }
   835 
   836 
   837 void
   838 draw_fringe_bitmap (struct window *w, struct glyph_row *row, int left_p)
   839 {
   840   int overlay = 0;
   841 
   842   if (left_p == row->reversed_p && row->cursor_in_fringe_p)
   843     {
   844       Lisp_Object cursor = Qnil;
   845 
   846       switch (w->phys_cursor_type)
   847         {
   848         case HOLLOW_BOX_CURSOR:
   849           if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits))
   850             cursor = Qhollow;
   851           else
   852             cursor = Qhollow_small;
   853           break;
   854         case FILLED_BOX_CURSOR:
   855           cursor = Qbox;
   856           break;
   857         case BAR_CURSOR:
   858           cursor = Qbar;
   859           break;
   860         case HBAR_CURSOR:
   861           cursor = Qhbar;
   862           break;
   863         case NO_CURSOR:
   864         default:
   865           w->phys_cursor_on_p = 0;
   866           row->cursor_in_fringe_p = 0;
   867           break;
   868         }
   869       if (!NILP (cursor))
   870         {
   871           int bm = get_logical_cursor_bitmap (w, cursor);
   872           if (bm != NO_FRINGE_BITMAP)
   873             {
   874               draw_fringe_bitmap_1 (w, row, left_p, 2, bm);
   875               overlay = EQ (cursor, Qbox) ? 3 : 1;
   876             }
   877         }
   878     }
   879 
   880   draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
   881 
   882   if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
   883     draw_fringe_bitmap_1 (w, row, 1, 1, row->overlay_arrow_bitmap);
   884 }
   885 
   886 
   887 /* Draw fringe bitmaps for glyph row ROW on window W.  Call this
   888    function with input blocked.  */
   889 
   890 void
   891 draw_row_fringe_bitmaps (struct window *w, struct glyph_row *row)
   892 {
   893   eassert (input_blocked_p ());
   894 
   895   /* If row is completely invisible, because of vscrolling, we
   896      don't have to draw anything.  */
   897   if (row->visible_height <= 0)
   898     return;
   899 
   900   if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
   901     draw_fringe_bitmap (w, row, 1);
   902 
   903   if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
   904     draw_fringe_bitmap (w, row, 0);
   905 }
   906 
   907 /* Draw the fringes of window W.  Only fringes for rows marked for
   908    update in redraw_fringe_bitmaps_p are drawn.
   909 
   910    Return nonzero if left or right fringe was redrawn in any way.
   911 
   912    If NO_FRINGE_P is non-zero, also return nonzero if either fringe
   913    has zero width.
   914 
   915    A return nonzero value indicates that the vertical line between
   916    windows needs update (as it may be drawn in the fringe).
   917 */
   918 
   919 bool
   920 draw_window_fringes (struct window *w, bool no_fringe_p)
   921 {
   922   struct glyph_row *row;
   923   int yb = window_text_bottom_y (w);
   924   int nrows = w->current_matrix->nrows;
   925   int y, rn;
   926   bool updated_p = 0;
   927 
   928   if (w->pseudo_window_p)
   929     return updated_p;
   930 
   931   /* We must switch to the window's buffer to use its local value of
   932      the fringe face, in case it's been remapped in face-remapping-alist.  */
   933   Lisp_Object window_buffer = w->contents;
   934   struct buffer *oldbuf = current_buffer;
   935   set_buffer_internal_1 (XBUFFER (window_buffer));
   936 
   937   /* Must draw line if no fringe */
   938   if (no_fringe_p
   939       && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
   940           || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
   941     updated_p = 1;
   942 
   943   for (y = w->vscroll, rn = 0, row = w->current_matrix->rows;
   944        y < yb && rn < nrows;
   945        y += row->height, ++row, ++rn)
   946     {
   947       if (!row->redraw_fringe_bitmaps_p)
   948         continue;
   949       draw_row_fringe_bitmaps (w, row);
   950       row->redraw_fringe_bitmaps_p = 0;
   951       updated_p = 1;
   952     }
   953 
   954   set_buffer_internal_1 (oldbuf);
   955 
   956   return updated_p;
   957 }
   958 
   959 
   960 /* Recalculate the bitmaps to show in the fringes of window W.
   961    Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p.
   962 
   963    If KEEP_CURRENT_P is 0, update current_matrix too.  */
   964 
   965 bool
   966 update_window_fringes (struct window *w, bool keep_current_p)
   967 {
   968   struct glyph_row *row, *cur = 0;
   969   int yb = window_text_bottom_y (w);
   970   int rn, nrows = w->current_matrix->nrows;
   971   int y;
   972   bool redraw_p = 0;
   973   Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
   974   Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
   975   Lisp_Object empty_pos;
   976   Lisp_Object ind = Qnil;
   977 #define MAX_BITMAP_CACHE (8*4)
   978   int bitmap_cache[MAX_BITMAP_CACHE];
   979   int top_ind_rn, bot_ind_rn;
   980   int top_ind_min_y, bot_ind_max_y;
   981 
   982   /* top_ind_rn is set to a nonnegative value whenever
   983      row->indicate_bob_p is set, so it's OK that top_row_ends_at_zv_p
   984      is not initialized here.  Similarly for bot_ind_rn,
   985      row->indicate_eob_p and bot_row_ends_at_zv_p.  */
   986   int top_row_ends_at_zv_p UNINIT, bot_row_ends_at_zv_p UNINIT;
   987 
   988   if (w->pseudo_window_p)
   989     return 0;
   990 
   991   specpdl_ref count = SPECPDL_INDEX ();
   992 
   993   /* This function could be called for redisplaying non-selected
   994      windows, in which case point has been temporarily moved to that
   995      window's window-point.  So we cannot afford quitting out of here,
   996      as point is restored after this function returns.  */
   997   specbind (Qinhibit_quit, Qt);
   998 
   999   if (!MINI_WINDOW_P (w)
  1000       && (ind = BVAR (XBUFFER (w->contents), indicate_buffer_boundaries), !NILP (ind)))
  1001     {
  1002       if (EQ (ind, Qleft) || EQ (ind, Qright))
  1003         boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
  1004       else if (CONSP (ind) && CONSP (XCAR (ind)))
  1005         {
  1006           Lisp_Object pos;
  1007           if (pos = Fassq (Qt, ind), !NILP (pos))
  1008             boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
  1009           if (pos = Fassq (Qtop, ind), !NILP (pos))
  1010             boundary_top = XCDR (pos);
  1011           if (pos = Fassq (Qbottom, ind), !NILP (pos))
  1012             boundary_bot = XCDR (pos);
  1013           if (pos = Fassq (Qup, ind), !NILP (pos))
  1014             arrow_top = XCDR (pos);
  1015           if (pos = Fassq (Qdown, ind), !NILP (pos))
  1016             arrow_bot = XCDR (pos);
  1017         }
  1018       else
  1019         /* Anything else means boundary on left and no arrows.  */
  1020         boundary_top = boundary_bot = Qleft;
  1021     }
  1022 
  1023   top_ind_rn = bot_ind_rn = -1;
  1024   if (!NILP (ind))
  1025     {
  1026       for (y = w->vscroll, rn = 0;
  1027            y < yb && rn < nrows;
  1028            y += row->height, ++rn)
  1029         {
  1030           row = w->desired_matrix->rows + rn;
  1031           if (!row->enabled_p)
  1032             row = w->current_matrix->rows + rn;
  1033 
  1034           row->indicate_bob_p = row->indicate_top_line_p = 0;
  1035           row->indicate_eob_p = row->indicate_bottom_line_p = 0;
  1036 
  1037           if (!row->mode_line_p)
  1038             {
  1039               if (top_ind_rn < 0 && row->visible_height > 0)
  1040                 {
  1041                   if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->contents))
  1042                       && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
  1043                     row->indicate_bob_p = !NILP (boundary_top);
  1044                   else
  1045                     row->indicate_top_line_p = !NILP (arrow_top);
  1046                   top_ind_rn = rn;
  1047                 }
  1048 
  1049               if (bot_ind_rn < 0)
  1050                 {
  1051                   if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->contents))
  1052                       && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
  1053                     row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
  1054                   else if (y + row->height >= yb)
  1055                     row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn;
  1056                 }
  1057             }
  1058         }
  1059     }
  1060 
  1061   empty_pos = BVAR (XBUFFER (w->contents), indicate_empty_lines);
  1062   if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
  1063     empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
  1064 
  1065   for (y = 0; y < MAX_BITMAP_CACHE; y++)
  1066     bitmap_cache[y] = -1;
  1067 
  1068 #define LEFT_FRINGE(cache, which, partial_p)                    \
  1069   (bitmap_cache[cache*4+partial_p] >= 0                         \
  1070    ? bitmap_cache[cache*4+partial_p]                            \
  1071    : (bitmap_cache[cache*4+partial_p] =                         \
  1072       get_logical_fringe_bitmap (w, which, 0, partial_p)))
  1073 
  1074 #define RIGHT_FRINGE(cache, which, partial_p)                   \
  1075   (bitmap_cache[cache*4+2+partial_p] >= 0                       \
  1076    ? bitmap_cache[cache*4+2+partial_p]                          \
  1077    : (bitmap_cache[cache*4+2+partial_p] =                       \
  1078       get_logical_fringe_bitmap (w, which, 1, partial_p)))
  1079 
  1080 
  1081   /* Extend top-aligned top indicator (or bottom-aligned bottom
  1082      indicator) to adjacent rows if it doesn't fit in one row.  */
  1083   top_ind_min_y = bot_ind_max_y = -1;
  1084   if (top_ind_rn >= 0)
  1085     {
  1086       int bn = NO_FRINGE_BITMAP;
  1087 
  1088       row = w->desired_matrix->rows + top_ind_rn;
  1089       if (!row->enabled_p)
  1090         row = w->current_matrix->rows + top_ind_rn;
  1091 
  1092       top_row_ends_at_zv_p = row->ends_at_zv_p;
  1093       if (row->indicate_bob_p)
  1094         {
  1095           if (EQ (boundary_top, Qleft))
  1096             bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
  1097                   ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
  1098                   : LEFT_FRINGE (2, Qtop, 0));
  1099           else
  1100             bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
  1101                   ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
  1102                   : RIGHT_FRINGE (2, Qtop, 0));
  1103         }
  1104       else if (row->indicate_top_line_p)
  1105         {
  1106           if (EQ (arrow_top, Qleft))
  1107             bn = LEFT_FRINGE (6, Qup, 0);
  1108           else
  1109             bn = RIGHT_FRINGE (6, Qup, 0);
  1110         }
  1111 
  1112       if (bn != NO_FRINGE_BITMAP)
  1113         {
  1114           struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
  1115 
  1116           if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0)
  1117             {
  1118               struct glyph_row *row1;
  1119               int top_ind_max_y;
  1120 
  1121               top_ind_min_y = WINDOW_TAB_LINE_HEIGHT (w)
  1122                               + WINDOW_HEADER_LINE_HEIGHT (w);
  1123               top_ind_max_y = top_ind_min_y + fb->height;
  1124               if (top_ind_max_y > yb)
  1125                 top_ind_max_y = yb;
  1126 
  1127               for (y = row->y + row->height, rn = top_ind_rn + 1;
  1128                    y < top_ind_max_y && rn < nrows;
  1129                    y += row1->height, rn++)
  1130                 {
  1131                   if (bot_ind_rn >= 0 && rn >= bot_ind_rn)
  1132                     break;
  1133 
  1134                   row1 = w->desired_matrix->rows + rn;
  1135                   if (!row1->enabled_p)
  1136                     row1 = w->current_matrix->rows + rn;
  1137 
  1138                   row1->indicate_bob_p = row->indicate_bob_p;
  1139                   row1->indicate_top_line_p = row->indicate_top_line_p;
  1140                 }
  1141             }
  1142         }
  1143     }
  1144   if (bot_ind_rn >= 0)
  1145     {
  1146       int bn = NO_FRINGE_BITMAP;
  1147 
  1148       row = w->desired_matrix->rows + bot_ind_rn;
  1149       if (!row->enabled_p)
  1150         row = w->current_matrix->rows + bot_ind_rn;
  1151 
  1152       bot_row_ends_at_zv_p = row->ends_at_zv_p;
  1153       if (row->indicate_eob_p)
  1154         {
  1155           if (EQ (boundary_bot, Qleft))
  1156             bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
  1157           else
  1158             bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
  1159         }
  1160       else if (row->indicate_bottom_line_p)
  1161         {
  1162           if (EQ (arrow_bot, Qleft))
  1163             bn = LEFT_FRINGE (7, Qdown, 0);
  1164           else
  1165             bn = RIGHT_FRINGE (7, Qdown, 0);
  1166         }
  1167 
  1168       if (bn != NO_FRINGE_BITMAP)
  1169         {
  1170           struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
  1171 
  1172           if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0)
  1173             {
  1174               struct glyph_row *row1;
  1175               int bot_ind_min_y;
  1176 
  1177               bot_ind_max_y = row->y + row->visible_height;
  1178               bot_ind_min_y = bot_ind_max_y - fb->height;
  1179               if (bot_ind_min_y < WINDOW_TAB_LINE_HEIGHT (w)
  1180                                   + WINDOW_HEADER_LINE_HEIGHT (w))
  1181                 bot_ind_min_y = WINDOW_TAB_LINE_HEIGHT (w)
  1182                                 + WINDOW_HEADER_LINE_HEIGHT (w);
  1183 
  1184               for (y = row->y, rn = bot_ind_rn - 1;
  1185                    y >= bot_ind_min_y && rn >= 0;
  1186                    y -= row1->height, rn--)
  1187                 {
  1188                   if (top_ind_rn >= 0 && rn <= top_ind_rn)
  1189                     break;
  1190 
  1191                   row1 = w->desired_matrix->rows + rn;
  1192                   if (!row1->enabled_p)
  1193                     row1 = w->current_matrix->rows + rn;
  1194 
  1195                   row1->indicate_eob_p = row->indicate_eob_p;
  1196                   row1->indicate_bottom_line_p = row->indicate_bottom_line_p;
  1197                 }
  1198             }
  1199         }
  1200     }
  1201 
  1202   for (y = w->vscroll, rn = 0;
  1203        y < yb && rn < nrows;
  1204        y += row->height, rn++)
  1205     {
  1206       int left, right;
  1207       unsigned left_face_id, right_face_id;
  1208       int left_offset, right_offset;
  1209       bool periodic_p;
  1210 
  1211       row = w->desired_matrix->rows + rn;
  1212       cur = w->current_matrix->rows + rn;
  1213       if (!row->enabled_p)
  1214         row = cur;
  1215 
  1216       left_face_id = right_face_id = DEFAULT_FACE_ID;
  1217       left_offset = right_offset = 0;
  1218       periodic_p = 0;
  1219 
  1220       /* Decide which bitmap to draw in the left fringe.  */
  1221       if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
  1222         left = NO_FRINGE_BITMAP;
  1223       else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
  1224         {
  1225           left = row->left_user_fringe_bitmap;
  1226           left_face_id = row->left_user_fringe_face_id;
  1227         }
  1228       else if ((!row->reversed_p && row->truncated_on_left_p)
  1229                || (row->reversed_p && row->truncated_on_right_p))
  1230         left = LEFT_FRINGE (0, Qtruncation, 0);
  1231       else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
  1232         {
  1233           left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
  1234                   ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
  1235                   : LEFT_FRINGE (2, Qtop, 0));
  1236           if (top_ind_min_y >= 0)
  1237             left_offset = top_ind_min_y - row->y;
  1238         }
  1239       else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
  1240         {
  1241           left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
  1242           if (bot_ind_max_y >= 0)
  1243             left_offset = bot_ind_max_y - (row->y + row->visible_height);
  1244         }
  1245       else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
  1246                || (row->reversed_p && row->continued_p))
  1247         left = LEFT_FRINGE (4, Qcontinuation, 0);
  1248       else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
  1249         left = LEFT_FRINGE (5, Qempty_line, 0);
  1250       else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
  1251         {
  1252           left = LEFT_FRINGE (6, Qup, 0);
  1253           if (top_ind_min_y >= 0)
  1254             left_offset = top_ind_min_y - row->y;
  1255         }
  1256       else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
  1257         {
  1258           left = LEFT_FRINGE (7, Qdown, 0);
  1259           if (bot_ind_max_y >= 0)
  1260             left_offset = bot_ind_max_y - (row->y + row->visible_height);
  1261         }
  1262       else
  1263         left = NO_FRINGE_BITMAP;
  1264 
  1265       /* Decide which bitmap to draw in the right fringe.  */
  1266       if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
  1267         right = NO_FRINGE_BITMAP;
  1268       else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
  1269         {
  1270           right = row->right_user_fringe_bitmap;
  1271           right_face_id = row->right_user_fringe_face_id;
  1272         }
  1273       else if ((!row->reversed_p && row->truncated_on_right_p)
  1274                || (row->reversed_p && row->truncated_on_left_p))
  1275         right = RIGHT_FRINGE (0, Qtruncation, 0);
  1276       else if (row->indicate_bob_p && EQ (boundary_top, Qright))
  1277         {
  1278           right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
  1279                    ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
  1280                    : RIGHT_FRINGE (2, Qtop, 0));
  1281           if (top_ind_min_y >= 0)
  1282             right_offset = top_ind_min_y - row->y;
  1283         }
  1284       else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
  1285         {
  1286           right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
  1287           if (bot_ind_max_y >= 0)
  1288             right_offset = bot_ind_max_y - (row->y + row->visible_height);
  1289         }
  1290       else if ((!row->reversed_p && row->continued_p)
  1291                || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
  1292         right = RIGHT_FRINGE (4, Qcontinuation, 0);
  1293       else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
  1294         {
  1295           right = RIGHT_FRINGE (6, Qup, 0);
  1296           if (top_ind_min_y >= 0)
  1297             right_offset = top_ind_min_y - row->y;
  1298         }
  1299       else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
  1300         {
  1301           right = RIGHT_FRINGE (7, Qdown, 0);
  1302           if (bot_ind_max_y >= 0)
  1303             right_offset = bot_ind_max_y - (row->y + row->visible_height);
  1304         }
  1305       else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
  1306         right = RIGHT_FRINGE (5, Qempty_line, 0);
  1307       else
  1308         right = NO_FRINGE_BITMAP;
  1309 
  1310       periodic_p = (get_fringe_bitmap_data (left)->period != 0
  1311                     || get_fringe_bitmap_data (right)->period != 0);
  1312 
  1313       if (row->y != cur->y
  1314           || row->visible_height != cur->visible_height
  1315           || row->ends_at_zv_p != cur->ends_at_zv_p
  1316           || left != cur->left_fringe_bitmap
  1317           || right != cur->right_fringe_bitmap
  1318           || left_face_id != cur->left_fringe_face_id
  1319           || right_face_id != cur->right_fringe_face_id
  1320           || left_offset != cur->left_fringe_offset
  1321           || right_offset != cur->right_fringe_offset
  1322           || periodic_p != cur->fringe_bitmap_periodic_p
  1323           || cur->redraw_fringe_bitmaps_p)
  1324         {
  1325           redraw_p = 1, row->redraw_fringe_bitmaps_p = 1;
  1326           if (!keep_current_p)
  1327             {
  1328               cur->redraw_fringe_bitmaps_p = 1;
  1329               cur->left_fringe_bitmap = left;
  1330               cur->right_fringe_bitmap = right;
  1331               cur->left_fringe_face_id = left_face_id;
  1332               cur->right_fringe_face_id = right_face_id;
  1333               cur->left_fringe_offset = left_offset;
  1334               cur->right_fringe_offset = right_offset;
  1335               cur->fringe_bitmap_periodic_p = periodic_p;
  1336             }
  1337         }
  1338 
  1339       if (row->overlay_arrow_bitmap < 0)
  1340         row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0);
  1341 
  1342       if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
  1343         {
  1344           redraw_p = 1, row->redraw_fringe_bitmaps_p = 1;
  1345           if (!keep_current_p)
  1346             {
  1347               cur->redraw_fringe_bitmaps_p = 1;
  1348               cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
  1349             }
  1350         }
  1351 
  1352       row->left_fringe_bitmap = left;
  1353       row->right_fringe_bitmap = right;
  1354       row->left_fringe_face_id = left_face_id;
  1355       row->right_fringe_face_id = right_face_id;
  1356       row->left_fringe_offset = left_offset;
  1357       row->right_fringe_offset = right_offset;
  1358       row->fringe_bitmap_periodic_p = periodic_p;
  1359     }
  1360 
  1361   unbind_to (count, Qnil);
  1362 
  1363   return redraw_p && !keep_current_p;
  1364 }
  1365 
  1366 
  1367 
  1368 /* Free resources used by a user-defined bitmap.  */
  1369 
  1370 static void
  1371 destroy_fringe_bitmap (int n)
  1372 {
  1373   struct fringe_bitmap **fbp;
  1374 
  1375   fringe_faces[n] = Qnil;
  1376 
  1377   fbp = &fringe_bitmaps[n];
  1378   if (*fbp && (*fbp)->dynamic)
  1379     {
  1380       /* XXX Is SELECTED_FRAME OK here? */
  1381       struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
  1382       if (rif && rif->destroy_fringe_bitmap)
  1383         rif->destroy_fringe_bitmap (n);
  1384       xfree (*fbp);
  1385       *fbp = NULL;
  1386     }
  1387 
  1388   while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
  1389          && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
  1390     max_used_fringe_bitmap--;
  1391 }
  1392 
  1393 
  1394 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
  1395        1, 1, 0,
  1396        doc: /* Destroy fringe bitmap BITMAP.
  1397 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored.  */)
  1398   (Lisp_Object bitmap)
  1399 {
  1400   int n;
  1401 
  1402   CHECK_SYMBOL (bitmap);
  1403   n = lookup_fringe_bitmap (bitmap);
  1404   if (!n)
  1405     return Qnil;
  1406 
  1407   destroy_fringe_bitmap (n);
  1408 
  1409   if (n >= MAX_STANDARD_FRINGE_BITMAPS)
  1410     {
  1411       Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
  1412       /* It would be better to remove the fringe property.  */
  1413       Fput (bitmap, Qfringe, Qnil);
  1414     }
  1415 
  1416   return Qnil;
  1417 }
  1418 
  1419 
  1420 /* Initialize bitmap bit.
  1421 
  1422    On X, we bit-swap the built-in bitmaps and reduce bitmap
  1423    from short to char array if width is <= 8 bits.
  1424 
  1425    On MAC with big-endian CPU, we need to byte-swap each short.
  1426 
  1427    On W32 and MAC (little endian), there's no need to do this.
  1428 */
  1429 
  1430 #if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK)
  1431 static const unsigned char swap_nibble[16] = {
  1432   0x0, 0x8, 0x4, 0xc,           /* 0000 1000 0100 1100 */
  1433   0x2, 0xa, 0x6, 0xe,           /* 0010 1010 0110 1110 */
  1434   0x1, 0x9, 0x5, 0xd,           /* 0001 1001 0101 1101 */
  1435   0x3, 0xb, 0x7, 0xf};          /* 0011 1011 0111 1111 */
  1436 #endif                          /* HAVE_X_WINDOWS */
  1437 
  1438 static void
  1439 init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
  1440 {
  1441   if (once_p || fb->dynamic)
  1442     {
  1443 #if defined (HAVE_X_WINDOWS)
  1444       unsigned short *bits = fb->bits;
  1445       int j;
  1446 
  1447 #ifdef USE_CAIRO
  1448       for (j = 0; j < fb->height; j++)
  1449         {
  1450           unsigned short b = *bits;
  1451 #ifdef WORDS_BIGENDIAN
  1452           *bits++ = (b << (16 - fb->width));
  1453 #else
  1454           b = (unsigned short)((swap_nibble[b & 0xf] << 12)
  1455                                | (swap_nibble[(b>>4) & 0xf] << 8)
  1456                                | (swap_nibble[(b>>8) & 0xf] << 4)
  1457                                | (swap_nibble[(b>>12) & 0xf]));
  1458           *bits++ = (b >> (16 - fb->width));
  1459 #endif
  1460         }
  1461 #else  /* not USE_CAIRO */
  1462       if (fb->width <= 8)
  1463         {
  1464           unsigned char *cbits = (unsigned char *)fb->bits;
  1465           for (j = 0; j < fb->height; j++)
  1466             {
  1467               unsigned short b = *bits++;
  1468               unsigned char c;
  1469               c = (unsigned char)((swap_nibble[b & 0xf] << 4)
  1470                                   | (swap_nibble[(b>>4) & 0xf]));
  1471               *cbits++ = (c >> (8 - fb->width));
  1472             }
  1473         }
  1474       else
  1475         {
  1476           for (j = 0; j < fb->height; j++)
  1477             {
  1478               unsigned short b = *bits;
  1479               b = (unsigned short)((swap_nibble[b & 0xf] << 12)
  1480                                    | (swap_nibble[(b>>4) & 0xf] << 8)
  1481                                    | (swap_nibble[(b>>8) & 0xf] << 4)
  1482                                    | (swap_nibble[(b>>12) & 0xf]));
  1483               b >>= (16 - fb->width);
  1484 #ifdef WORDS_BIGENDIAN
  1485               b = bswap_16 (b);
  1486 #endif
  1487               *bits++ = b;
  1488             }
  1489         }
  1490 #endif /* not USE_CAIRO */
  1491 #endif /* HAVE_X_WINDOWS */
  1492 
  1493 #if !defined(HAVE_X_WINDOWS) && defined (HAVE_PGTK)
  1494       unsigned short *bits = fb->bits;
  1495       int j;
  1496 
  1497       for (j = 0; j < fb->height; j++)
  1498         {
  1499           unsigned short b = *bits;
  1500 #ifdef WORDS_BIGENDIAN
  1501           *bits++ = (b << (16 - fb->width));
  1502 #else
  1503           b = (unsigned short)((swap_nibble[b & 0xf] << 12)
  1504                                | (swap_nibble[(b>>4) & 0xf] << 8)
  1505                                | (swap_nibble[(b>>8) & 0xf] << 4)
  1506                                | (swap_nibble[(b>>12) & 0xf]));
  1507           *bits++ = (b >> (16 - fb->width));
  1508 #endif
  1509         }
  1510 #endif /* !HAVE_X_WINDOWS && HAVE_PGTK */
  1511 
  1512 #ifdef HAVE_NTGUI
  1513       unsigned short *bits = fb->bits;
  1514       int j;
  1515       for (j = 0; j < fb->height; j++)
  1516         {
  1517           unsigned short b = *bits;
  1518           b <<= (16 - fb->width);
  1519           /* Windows is little-endian, so the next line is always
  1520              needed.  */
  1521           b = ((b >> 8) | (b << 8));
  1522           *bits++ = b;
  1523         }
  1524 #endif
  1525     }
  1526 
  1527   if (!once_p)
  1528     {
  1529       /* XXX Is SELECTED_FRAME OK here? */
  1530       struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
  1531 
  1532       destroy_fringe_bitmap (which);
  1533 
  1534       if (rif && rif->define_fringe_bitmap)
  1535         rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
  1536 
  1537       fringe_bitmaps[which] = fb;
  1538       if (which >= max_used_fringe_bitmap)
  1539         max_used_fringe_bitmap = which + 1;
  1540     }
  1541 }
  1542 
  1543 
  1544 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
  1545        2, 5, 0,
  1546        doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
  1547 BITMAP is a symbol identifying the new fringe bitmap.
  1548 BITS is either a string or a vector of integers.
  1549 HEIGHT is height of bitmap.  If HEIGHT is nil, use length of BITS.
  1550 WIDTH must be an integer from 1 to 16, or nil which defaults to 8.  An
  1551 error is signaled if WIDTH is outside this range.
  1552 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
  1553 indicating the positioning of the bitmap relative to the rows where it
  1554 is used; the default is to center the bitmap.  Fifth arg may also be a
  1555 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
  1556 should be repeated.
  1557 If BITMAP already exists, the existing definition is replaced.  */)
  1558   (Lisp_Object bitmap, Lisp_Object bits, Lisp_Object height, Lisp_Object width, Lisp_Object align)
  1559 {
  1560   int n, h, i, j;
  1561   unsigned short *b;
  1562   struct fringe_bitmap fb, *xfb;
  1563   int fill1 = 0, fill2 = 0;
  1564 
  1565   CHECK_SYMBOL (bitmap);
  1566   h = CHECK_VECTOR_OR_STRING (bits);
  1567 
  1568   if (NILP (height))
  1569     fb.height = h;
  1570   else
  1571     {
  1572       CHECK_FIXNUM (height);
  1573       fb.height = max (0, min (XFIXNUM (height), 255));
  1574       if (fb.height > h)
  1575         {
  1576           fill1 = (fb.height - h) / 2;
  1577           fill2 = fb.height - h - fill1;
  1578         }
  1579     }
  1580 
  1581   if (NILP (width))
  1582     fb.width = 8;
  1583   else
  1584     {
  1585       CHECK_FIXNUM (width);
  1586       fb.width = max (1, min (XFIXNUM (width), 16));
  1587       if (fb.width != XFIXNUM (width))
  1588         args_out_of_range (width, build_string ("Width must be from 1 to 16"));
  1589     }
  1590 
  1591   fb.period = 0;
  1592   fb.align = ALIGN_BITMAP_CENTER;
  1593 
  1594   if (CONSP (align))
  1595     {
  1596       Lisp_Object period = XCDR (align);
  1597       if (CONSP (period))
  1598         {
  1599           period = XCAR (period);
  1600           if (!NILP (period))
  1601             {
  1602               fb.period = fb.height;
  1603               fb.height = 255;
  1604             }
  1605         }
  1606       align = XCAR (align);
  1607     }
  1608   if (EQ (align, Qtop))
  1609     fb.align = ALIGN_BITMAP_TOP;
  1610   else if (EQ (align, Qbottom))
  1611     fb.align = ALIGN_BITMAP_BOTTOM;
  1612   else if (!NILP (align) && !EQ (align, Qcenter))
  1613     error ("Bad align argument");
  1614 
  1615   n = lookup_fringe_bitmap (bitmap);
  1616   if (!n)
  1617     {
  1618       if (max_used_fringe_bitmap < max_fringe_bitmaps)
  1619         n = max_used_fringe_bitmap++;
  1620       else
  1621         {
  1622           for (n = MAX_STANDARD_FRINGE_BITMAPS;
  1623                n < max_fringe_bitmaps;
  1624                n++)
  1625             if (fringe_bitmaps[n] == NULL)
  1626               break;
  1627 
  1628           if (n == max_fringe_bitmaps)
  1629             {
  1630               int bitmaps = max_fringe_bitmaps + 20;
  1631               if (MAX_FRINGE_BITMAPS < bitmaps)
  1632                 error ("No free fringe bitmap slots");
  1633 
  1634               i = max_fringe_bitmaps;
  1635               fringe_bitmaps = xrealloc (fringe_bitmaps,
  1636                                          bitmaps * sizeof *fringe_bitmaps);
  1637               fringe_faces = xrealloc (fringe_faces,
  1638                                        bitmaps * sizeof *fringe_faces);
  1639 
  1640               for (i = max_fringe_bitmaps; i < bitmaps; i++)
  1641                 {
  1642                   fringe_bitmaps[i] = NULL;
  1643                   fringe_faces[i] = Qnil;
  1644                 }
  1645 
  1646               max_fringe_bitmaps = bitmaps;
  1647             }
  1648         }
  1649 
  1650       Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
  1651       Fput (bitmap, Qfringe, make_fixnum (n));
  1652     }
  1653 
  1654   fb.dynamic = true;
  1655 
  1656   xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW);
  1657   fb.bits = b = (unsigned short *) (xfb + 1);
  1658 
  1659   j = 0;
  1660   while (j < fb.height)
  1661     {
  1662       for (i = 0; i < fill1 && j < fb.height; i++)
  1663         b[j++] = 0;
  1664       for (i = 0; i < h && j < fb.height; i++)
  1665         {
  1666           Lisp_Object elt = Faref (bits, make_fixnum (i));
  1667           b[j++] = FIXNUMP (elt) ? XFIXNUM (elt) : 0;
  1668         }
  1669       for (i = 0; i < fill2 && j < fb.height; i++)
  1670         b[j++] = 0;
  1671     }
  1672 
  1673   *xfb = fb;
  1674 
  1675   init_fringe_bitmap (n, xfb, 0);
  1676 
  1677   return bitmap;
  1678 }
  1679 
  1680 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
  1681        1, 2, 0,
  1682        doc: /* Set face for fringe bitmap BITMAP to FACE.
  1683 FACE is merged with the `fringe' face, so normally FACE should specify
  1684 only the foreground color.
  1685 If FACE is nil, reset face to default fringe face.  */)
  1686   (Lisp_Object bitmap, Lisp_Object face)
  1687 {
  1688   int n;
  1689 
  1690   CHECK_SYMBOL (bitmap);
  1691   n = lookup_fringe_bitmap (bitmap);
  1692   if (!n)
  1693     error ("Undefined fringe bitmap");
  1694 
  1695   /* We used to check, as a convenience to callers, for basic face
  1696      validity here, but since validity can depend on the specific
  1697      _window_ in which this buffer is being displayed, defer the check
  1698      to redisplay, which can cope with bad face specifications.  */
  1699   fringe_faces[n] = face;
  1700   return Qnil;
  1701 }
  1702 
  1703 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
  1704        0, 2, 0,
  1705        doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
  1706 If WINDOW is nil, use selected window.  If POS is nil, use value of point
  1707 in that window.  Return value is a list (LEFT RIGHT OV), where LEFT
  1708 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
  1709 RIGHT is similar for the right fringe, and OV is non-nil if there is an
  1710 overlay arrow in the left fringe.
  1711 Return nil if POS is not visible in WINDOW.  */)
  1712   (Lisp_Object pos, Lisp_Object window)
  1713 {
  1714   struct window *w;
  1715   struct glyph_row *row;
  1716   ptrdiff_t textpos;
  1717 
  1718   w = decode_any_window (window);
  1719   XSETWINDOW (window, w);
  1720 
  1721   if (!NILP (pos))
  1722     {
  1723       EMACS_INT p = fix_position (pos);
  1724       if (! (BEGV <= p && p <= ZV))
  1725         args_out_of_range (window, pos);
  1726       textpos = p;
  1727     }
  1728   else if (w == XWINDOW (selected_window))
  1729     textpos = PT;
  1730   else
  1731     textpos = marker_position (w->pointm);
  1732 
  1733   row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
  1734   row = row_containing_pos (w, textpos, row, NULL, 0);
  1735   if (row)
  1736     return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
  1737                   get_fringe_bitmap_name (row->right_fringe_bitmap),
  1738                   (row->overlay_arrow_bitmap == 0 ? Qnil
  1739                    : row->overlay_arrow_bitmap < 0 ? Qt
  1740                    : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
  1741   else
  1742     return Qnil;
  1743 }
  1744 
  1745 
  1746 /***********************************************************************
  1747                             Initialization
  1748  ***********************************************************************/
  1749 
  1750 void
  1751 syms_of_fringe (void)
  1752 {
  1753   DEFSYM (Qtruncation, "truncation");
  1754   DEFSYM (Qcontinuation, "continuation");
  1755   DEFSYM (Qoverlay_arrow, "overlay-arrow");
  1756   DEFSYM (Qempty_line, "empty-line");
  1757   DEFSYM (Qtop_bottom, "top-bottom");
  1758   DEFSYM (Qhollow_small, "hollow-small");
  1759 
  1760   defsubr (&Sdestroy_fringe_bitmap);
  1761   defsubr (&Sdefine_fringe_bitmap);
  1762   defsubr (&Sfringe_bitmaps_at_pos);
  1763   defsubr (&Sset_fringe_bitmap_face);
  1764 
  1765   DEFVAR_LISP ("overflow-newline-into-fringe", Voverflow_newline_into_fringe,
  1766     doc: /* Non-nil means that newline may flow into the right fringe.
  1767 This means that display lines that are exactly as wide as the window
  1768 \(not counting the final newline) will occupy only one screen line, by
  1769 showing (or hiding) the final newline in the right fringe; when point
  1770 is at the final newline, the cursor is shown in the right fringe.
  1771 If nil, also continue lines which are exactly as wide as the window.  */);
  1772   Voverflow_newline_into_fringe = Qt;
  1773 
  1774   DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps,
  1775     doc: /* List of fringe bitmap symbols.  */);
  1776   Vfringe_bitmaps = Qnil;
  1777 }
  1778 
  1779 /* Garbage collection hook */
  1780 
  1781 void
  1782 mark_fringe_data (void)
  1783 {
  1784   mark_objects (fringe_faces, max_fringe_bitmaps);
  1785 }
  1786 
  1787 /* Initialize this module when Emacs starts.  */
  1788 
  1789 static void init_fringe_once_for_pdumper (void);
  1790 
  1791 void
  1792 init_fringe_once (void)
  1793 {
  1794   pdumper_do_now_and_after_load (init_fringe_once_for_pdumper);
  1795 }
  1796 
  1797 static void
  1798 init_fringe_once_for_pdumper (void)
  1799 {
  1800   for (int bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
  1801     init_fringe_bitmap (bt, &standard_bitmaps[bt], 1);
  1802 }
  1803 
  1804 void
  1805 init_fringe (void)
  1806 {
  1807   max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
  1808 
  1809   fringe_bitmaps = xzalloc (max_fringe_bitmaps * sizeof *fringe_bitmaps);
  1810 
  1811   verify (NIL_IS_ZERO);
  1812   fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
  1813 }
  1814 
  1815 void
  1816 gui_init_fringe (struct redisplay_interface *rif)
  1817 {
  1818   int bt;
  1819 
  1820   if (!rif || !rif->define_fringe_bitmap)
  1821     return;
  1822 
  1823   /* Set up the standard fringe bitmaps.  */
  1824   for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
  1825     {
  1826       struct fringe_bitmap *fb = &standard_bitmaps[bt];
  1827       if (!fringe_bitmaps[bt])
  1828         rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
  1829     }
  1830 
  1831   /* Set up user-defined fringe bitmaps that might have been defined
  1832      before the frame of this kind was initialized.  This can happen
  1833      if Emacs is started as a daemon and the init files define fringe
  1834      bitmaps.  */
  1835   for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
  1836     {
  1837       struct fringe_bitmap *fb = fringe_bitmaps[bt];
  1838       if (fb)
  1839         rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
  1840     }
  1841 }
  1842 
  1843 /* Call frame F's specific define_fringe_bitmap method for a fringe
  1844    bitmap number N.  Called by various *term.c functions when they
  1845    need to display a fringe bitmap whose terminal-specific data is not
  1846    available.  */
  1847 void
  1848 gui_define_fringe_bitmap (struct frame *f, int n)
  1849 {
  1850   struct redisplay_interface *rif = FRAME_RIF (f);
  1851 
  1852   if (!rif || !rif->define_fringe_bitmap || n >= max_used_fringe_bitmap)
  1853     return;
  1854 
  1855   struct fringe_bitmap *fb = fringe_bitmaps[n];
  1856   if (fb)
  1857     rif->define_fringe_bitmap (n, fb->bits, fb->height, fb->width);
  1858 }
  1859 
  1860 #ifdef HAVE_NTGUI
  1861 void
  1862 w32_reset_fringes (void)
  1863 {
  1864   /* Destroy row bitmaps.  */
  1865   int bt;
  1866   struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
  1867 
  1868   if (!rif || !rif->destroy_fringe_bitmap)
  1869     return;
  1870 
  1871   for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
  1872     rif->destroy_fringe_bitmap (bt);
  1873 }
  1874 
  1875 #endif /* HAVE_NTGUI */

/* [<][>][^][v][top][bottom][index][help] */