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    The Android port tries to follow X as closely as possible, so do
  1426    that there too.
  1427 
  1428    On MAC with big-endian CPU, we need to byte-swap each short.
  1429 
  1430    On W32 and MAC (little endian), there's no need to do this.
  1431 */
  1432 
  1433 #if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) || defined (HAVE_ANDROID)
  1434 static const unsigned char swap_nibble[16] =
  1435   {
  1436     0x0, 0x8, 0x4, 0xc,           /* 0000 1000 0100 1100 */
  1437     0x2, 0xa, 0x6, 0xe,           /* 0010 1010 0110 1110 */
  1438     0x1, 0x9, 0x5, 0xd,           /* 0001 1001 0101 1101 */
  1439     0x3, 0xb, 0x7, 0xf,           /* 0011 1011 0111 1111 */
  1440   };
  1441 #endif
  1442 
  1443 static void
  1444 init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
  1445 {
  1446   if (once_p || fb->dynamic)
  1447     {
  1448 #if defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
  1449       unsigned short *bits = fb->bits;
  1450       int j;
  1451 
  1452 #ifdef USE_CAIRO
  1453       for (j = 0; j < fb->height; j++)
  1454         {
  1455           unsigned short b = *bits;
  1456 #ifdef WORDS_BIGENDIAN
  1457           *bits++ = (b << (16 - fb->width));
  1458 #else
  1459           b = (unsigned short)((swap_nibble[b & 0xf] << 12)
  1460                                | (swap_nibble[(b>>4) & 0xf] << 8)
  1461                                | (swap_nibble[(b>>8) & 0xf] << 4)
  1462                                | (swap_nibble[(b>>12) & 0xf]));
  1463           *bits++ = (b >> (16 - fb->width));
  1464 #endif
  1465         }
  1466 #else  /* not USE_CAIRO */
  1467       if (fb->width <= 8)
  1468         {
  1469           unsigned char *cbits = (unsigned char *)fb->bits;
  1470           for (j = 0; j < fb->height; j++)
  1471             {
  1472               unsigned short b = *bits++;
  1473               unsigned char c;
  1474               c = (unsigned char)((swap_nibble[b & 0xf] << 4)
  1475                                   | (swap_nibble[(b>>4) & 0xf]));
  1476               *cbits++ = (c >> (8 - fb->width));
  1477             }
  1478         }
  1479       else
  1480         {
  1481           for (j = 0; j < fb->height; j++)
  1482             {
  1483               unsigned short b = *bits;
  1484               b = (unsigned short)((swap_nibble[b & 0xf] << 12)
  1485                                    | (swap_nibble[(b>>4) & 0xf] << 8)
  1486                                    | (swap_nibble[(b>>8) & 0xf] << 4)
  1487                                    | (swap_nibble[(b>>12) & 0xf]));
  1488               b >>= (16 - fb->width);
  1489 #ifdef WORDS_BIGENDIAN
  1490               b = bswap_16 (b);
  1491 #endif
  1492               *bits++ = b;
  1493             }
  1494         }
  1495 #endif /* not USE_CAIRO */
  1496 #endif /* HAVE_X_WINDOWS || HAVE_ANDROID */
  1497 
  1498 #if !defined(HAVE_X_WINDOWS) && defined (HAVE_PGTK)
  1499       unsigned short *bits = fb->bits;
  1500       int j;
  1501 
  1502       for (j = 0; j < fb->height; j++)
  1503         {
  1504           unsigned short b = *bits;
  1505 #ifdef WORDS_BIGENDIAN
  1506           *bits++ = (b << (16 - fb->width));
  1507 #else
  1508           b = (unsigned short)((swap_nibble[b & 0xf] << 12)
  1509                                | (swap_nibble[(b>>4) & 0xf] << 8)
  1510                                | (swap_nibble[(b>>8) & 0xf] << 4)
  1511                                | (swap_nibble[(b>>12) & 0xf]));
  1512           *bits++ = (b >> (16 - fb->width));
  1513 #endif
  1514         }
  1515 #endif /* !HAVE_X_WINDOWS && HAVE_PGTK */
  1516 
  1517 #ifdef HAVE_NTGUI
  1518       unsigned short *bits = fb->bits;
  1519       int j;
  1520       for (j = 0; j < fb->height; j++)
  1521         {
  1522           unsigned short b = *bits;
  1523           b <<= (16 - fb->width);
  1524           /* Windows is little-endian, so the next line is always
  1525              needed.  */
  1526           b = ((b >> 8) | (b << 8));
  1527           *bits++ = b;
  1528         }
  1529 #endif
  1530     }
  1531 
  1532   if (!once_p)
  1533     {
  1534       /* XXX Is SELECTED_FRAME OK here? */
  1535       struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
  1536 
  1537       destroy_fringe_bitmap (which);
  1538 
  1539       if (rif && rif->define_fringe_bitmap)
  1540         rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
  1541 
  1542       fringe_bitmaps[which] = fb;
  1543       if (which >= max_used_fringe_bitmap)
  1544         max_used_fringe_bitmap = which + 1;
  1545     }
  1546 }
  1547 
  1548 
  1549 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
  1550        2, 5, 0,
  1551        doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
  1552 BITMAP is a symbol identifying the new fringe bitmap.
  1553 BITS is either a string or a vector of integers.
  1554 HEIGHT is height of bitmap.  If HEIGHT is nil, use length of BITS.
  1555 WIDTH must be an integer from 1 to 16, or nil which defaults to 8.  An
  1556 error is signaled if WIDTH is outside this range.
  1557 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
  1558 indicating the positioning of the bitmap relative to the rows where it
  1559 is used; the default is to center the bitmap.  Fifth arg may also be a
  1560 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
  1561 should be repeated.
  1562 If BITMAP already exists, the existing definition is replaced.  */)
  1563   (Lisp_Object bitmap, Lisp_Object bits, Lisp_Object height, Lisp_Object width, Lisp_Object align)
  1564 {
  1565   int n, h, i, j;
  1566   unsigned short *b;
  1567   struct fringe_bitmap fb, *xfb;
  1568   int fill1 = 0, fill2 = 0;
  1569 
  1570   CHECK_SYMBOL (bitmap);
  1571   h = CHECK_VECTOR_OR_STRING (bits);
  1572 
  1573   if (NILP (height))
  1574     fb.height = h;
  1575   else
  1576     {
  1577       CHECK_FIXNUM (height);
  1578       fb.height = max (0, min (XFIXNUM (height), 255));
  1579       if (fb.height > h)
  1580         {
  1581           fill1 = (fb.height - h) / 2;
  1582           fill2 = fb.height - h - fill1;
  1583         }
  1584     }
  1585 
  1586   if (NILP (width))
  1587     fb.width = 8;
  1588   else
  1589     {
  1590       CHECK_FIXNUM (width);
  1591       fb.width = max (1, min (XFIXNUM (width), 16));
  1592       if (fb.width != XFIXNUM (width))
  1593         args_out_of_range (width, build_string ("Width must be from 1 to 16"));
  1594     }
  1595 
  1596   fb.period = 0;
  1597   fb.align = ALIGN_BITMAP_CENTER;
  1598 
  1599   if (CONSP (align))
  1600     {
  1601       Lisp_Object period = XCDR (align);
  1602       if (CONSP (period))
  1603         {
  1604           period = XCAR (period);
  1605           if (!NILP (period))
  1606             {
  1607               fb.period = fb.height;
  1608               fb.height = 255;
  1609             }
  1610         }
  1611       align = XCAR (align);
  1612     }
  1613   if (EQ (align, Qtop))
  1614     fb.align = ALIGN_BITMAP_TOP;
  1615   else if (EQ (align, Qbottom))
  1616     fb.align = ALIGN_BITMAP_BOTTOM;
  1617   else if (!NILP (align) && !EQ (align, Qcenter))
  1618     error ("Bad align argument");
  1619 
  1620   n = lookup_fringe_bitmap (bitmap);
  1621   if (!n)
  1622     {
  1623       if (max_used_fringe_bitmap < max_fringe_bitmaps)
  1624         n = max_used_fringe_bitmap++;
  1625       else
  1626         {
  1627           for (n = MAX_STANDARD_FRINGE_BITMAPS;
  1628                n < max_fringe_bitmaps;
  1629                n++)
  1630             if (fringe_bitmaps[n] == NULL)
  1631               break;
  1632 
  1633           if (n == max_fringe_bitmaps)
  1634             {
  1635               int bitmaps = max_fringe_bitmaps + 20;
  1636               if (MAX_FRINGE_BITMAPS < bitmaps)
  1637                 error ("No free fringe bitmap slots");
  1638 
  1639               i = max_fringe_bitmaps;
  1640               fringe_bitmaps = xrealloc (fringe_bitmaps,
  1641                                          bitmaps * sizeof *fringe_bitmaps);
  1642               fringe_faces = xrealloc (fringe_faces,
  1643                                        bitmaps * sizeof *fringe_faces);
  1644 
  1645               for (i = max_fringe_bitmaps; i < bitmaps; i++)
  1646                 {
  1647                   fringe_bitmaps[i] = NULL;
  1648                   fringe_faces[i] = Qnil;
  1649                 }
  1650 
  1651               max_fringe_bitmaps = bitmaps;
  1652             }
  1653         }
  1654 
  1655       Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
  1656       Fput (bitmap, Qfringe, make_fixnum (n));
  1657     }
  1658 
  1659   fb.dynamic = true;
  1660 
  1661   xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW);
  1662   fb.bits = b = (unsigned short *) (xfb + 1);
  1663 
  1664   j = 0;
  1665   while (j < fb.height)
  1666     {
  1667       for (i = 0; i < fill1 && j < fb.height; i++)
  1668         b[j++] = 0;
  1669       for (i = 0; i < h && j < fb.height; i++)
  1670         {
  1671           Lisp_Object elt = Faref (bits, make_fixnum (i));
  1672           b[j++] = FIXNUMP (elt) ? XFIXNUM (elt) : 0;
  1673         }
  1674       for (i = 0; i < fill2 && j < fb.height; i++)
  1675         b[j++] = 0;
  1676     }
  1677 
  1678   *xfb = fb;
  1679 
  1680   init_fringe_bitmap (n, xfb, 0);
  1681 
  1682   return bitmap;
  1683 }
  1684 
  1685 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
  1686        1, 2, 0,
  1687        doc: /* Set face for fringe bitmap BITMAP to FACE.
  1688 FACE is merged with the `fringe' face, so normally FACE should specify
  1689 only the foreground color.
  1690 If FACE is nil, reset face to default fringe face.  */)
  1691   (Lisp_Object bitmap, Lisp_Object face)
  1692 {
  1693   int n;
  1694 
  1695   CHECK_SYMBOL (bitmap);
  1696   n = lookup_fringe_bitmap (bitmap);
  1697   if (!n)
  1698     error ("Undefined fringe bitmap");
  1699 
  1700   /* We used to check, as a convenience to callers, for basic face
  1701      validity here, but since validity can depend on the specific
  1702      _window_ in which this buffer is being displayed, defer the check
  1703      to redisplay, which can cope with bad face specifications.  */
  1704   fringe_faces[n] = face;
  1705   return Qnil;
  1706 }
  1707 
  1708 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
  1709        0, 2, 0,
  1710        doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
  1711 If WINDOW is nil, use selected window.  If POS is nil, use value of point
  1712 in that window.  Return value is a list (LEFT RIGHT OV), where LEFT
  1713 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
  1714 RIGHT is similar for the right fringe, and OV is non-nil if there is an
  1715 overlay arrow in the left fringe.
  1716 Return nil if POS is not visible in WINDOW.  */)
  1717   (Lisp_Object pos, Lisp_Object window)
  1718 {
  1719   struct window *w;
  1720   struct glyph_row *row;
  1721   ptrdiff_t textpos;
  1722 
  1723   w = decode_any_window (window);
  1724   XSETWINDOW (window, w);
  1725 
  1726   if (!NILP (pos))
  1727     {
  1728       EMACS_INT p = fix_position (pos);
  1729       if (! (BEGV <= p && p <= ZV))
  1730         args_out_of_range (window, pos);
  1731       textpos = p;
  1732     }
  1733   else if (w == XWINDOW (selected_window))
  1734     textpos = PT;
  1735   else
  1736     textpos = marker_position (w->pointm);
  1737 
  1738   row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
  1739   row = row_containing_pos (w, textpos, row, NULL, 0);
  1740   if (row)
  1741     return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
  1742                   get_fringe_bitmap_name (row->right_fringe_bitmap),
  1743                   (row->overlay_arrow_bitmap == 0 ? Qnil
  1744                    : row->overlay_arrow_bitmap < 0 ? Qt
  1745                    : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
  1746   else
  1747     return Qnil;
  1748 }
  1749 
  1750 
  1751 /***********************************************************************
  1752                             Initialization
  1753  ***********************************************************************/
  1754 
  1755 void
  1756 syms_of_fringe (void)
  1757 {
  1758   DEFSYM (Qtruncation, "truncation");
  1759   DEFSYM (Qcontinuation, "continuation");
  1760   DEFSYM (Qoverlay_arrow, "overlay-arrow");
  1761   DEFSYM (Qempty_line, "empty-line");
  1762   DEFSYM (Qtop_bottom, "top-bottom");
  1763   DEFSYM (Qhollow_small, "hollow-small");
  1764 
  1765   defsubr (&Sdestroy_fringe_bitmap);
  1766   defsubr (&Sdefine_fringe_bitmap);
  1767   defsubr (&Sfringe_bitmaps_at_pos);
  1768   defsubr (&Sset_fringe_bitmap_face);
  1769 
  1770   DEFVAR_LISP ("overflow-newline-into-fringe", Voverflow_newline_into_fringe,
  1771     doc: /* Non-nil means that newline may flow into the right fringe.
  1772 This means that display lines that are exactly as wide as the window
  1773 \(not counting the final newline) will occupy only one screen line, by
  1774 showing (or hiding) the final newline in the right fringe; when point
  1775 is at the final newline, the cursor is shown in the right fringe.
  1776 If nil, also continue lines which are exactly as wide as the window.  */);
  1777   Voverflow_newline_into_fringe = Qt;
  1778 
  1779   DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps,
  1780     doc: /* List of fringe bitmap symbols.  */);
  1781   Vfringe_bitmaps = Qnil;
  1782 }
  1783 
  1784 /* Garbage collection hook */
  1785 
  1786 void
  1787 mark_fringe_data (void)
  1788 {
  1789   mark_objects (fringe_faces, max_fringe_bitmaps);
  1790 }
  1791 
  1792 /* Initialize this module when Emacs starts.  */
  1793 
  1794 static void init_fringe_once_for_pdumper (void);
  1795 
  1796 void
  1797 init_fringe_once (void)
  1798 {
  1799   pdumper_do_now_and_after_load (init_fringe_once_for_pdumper);
  1800 }
  1801 
  1802 static void
  1803 init_fringe_once_for_pdumper (void)
  1804 {
  1805   for (int bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
  1806     init_fringe_bitmap (bt, &standard_bitmaps[bt], 1);
  1807 }
  1808 
  1809 void
  1810 init_fringe (void)
  1811 {
  1812   max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
  1813 
  1814   fringe_bitmaps = xzalloc (max_fringe_bitmaps * sizeof *fringe_bitmaps);
  1815 
  1816   verify (NIL_IS_ZERO);
  1817   fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
  1818 }
  1819 
  1820 void
  1821 gui_init_fringe (struct redisplay_interface *rif)
  1822 {
  1823   int bt;
  1824 
  1825   if (!rif || !rif->define_fringe_bitmap)
  1826     return;
  1827 
  1828   /* Set up the standard fringe bitmaps.  */
  1829   for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
  1830     {
  1831       struct fringe_bitmap *fb = &standard_bitmaps[bt];
  1832       if (!fringe_bitmaps[bt])
  1833         rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
  1834     }
  1835 
  1836   /* Set up user-defined fringe bitmaps that might have been defined
  1837      before the frame of this kind was initialized.  This can happen
  1838      if Emacs is started as a daemon and the init files define fringe
  1839      bitmaps.  */
  1840   for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
  1841     {
  1842       struct fringe_bitmap *fb = fringe_bitmaps[bt];
  1843       if (fb)
  1844         rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
  1845     }
  1846 }
  1847 
  1848 /* Call frame F's specific define_fringe_bitmap method for a fringe
  1849    bitmap number N.  Called by various *term.c functions when they
  1850    need to display a fringe bitmap whose terminal-specific data is not
  1851    available.  */
  1852 void
  1853 gui_define_fringe_bitmap (struct frame *f, int n)
  1854 {
  1855   struct redisplay_interface *rif = FRAME_RIF (f);
  1856 
  1857   if (!rif || !rif->define_fringe_bitmap || n >= max_used_fringe_bitmap)
  1858     return;
  1859 
  1860   struct fringe_bitmap *fb = fringe_bitmaps[n];
  1861   if (fb)
  1862     rif->define_fringe_bitmap (n, fb->bits, fb->height, fb->width);
  1863 }
  1864 
  1865 #ifdef HAVE_NTGUI
  1866 void
  1867 w32_reset_fringes (void)
  1868 {
  1869   /* Destroy row bitmaps.  */
  1870   int bt;
  1871   struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
  1872 
  1873   if (!rif || !rif->destroy_fringe_bitmap)
  1874     return;
  1875 
  1876   for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
  1877     rif->destroy_fringe_bitmap (bt);
  1878 }
  1879 
  1880 #endif /* HAVE_NTGUI */

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