]> git.eshelyaron.com Git - emacs.git/commitdiff
Avoid crashes when fringe bitmaps are defined in daemon mode
authorEli Zaretskii <eliz@gnu.org>
Thu, 3 Mar 2022 18:31:33 +0000 (20:31 +0200)
committerEli Zaretskii <eliz@gnu.org>
Thu, 3 Mar 2022 18:31:33 +0000 (20:31 +0200)
* src/dispextern.h (gui_define_fringe_bitmap): Add prototype.
(max_used_fringe_bitmap): Add declaration.
* src/fringe.c (gui_define_fringe_bitmap): New function.
* src/w32term.c (w32_draw_fringe_bitmap):
* src/xterm.c (x_draw_fringe_bitmap) [USE_CAIRO]: Call
'gui_define_fringe_bitmap' if the terminal-specific bitmap data is
not available when a fringe bitmap is about to be drawn.  Don't
try to draw a bitmap that is not known to fringe.c.  (Bug#54183)

src/dispextern.h
src/fringe.c
src/w32term.c
src/xterm.c

index bc5f7a52e089fd63d260f89b4bb8299505dd99a6..65801596d5d95128a77bf4714527991bd2c57645 100644 (file)
@@ -3449,6 +3449,9 @@ bool update_window_fringes (struct window *, bool);
 
 void gui_init_fringe (struct redisplay_interface *);
 
+extern int max_used_fringe_bitmap;
+void gui_define_fringe_bitmap (struct frame *, int);
+
 #ifdef HAVE_NTGUI
 void w32_reset_fringes (void);
 #endif
index f857aedaf021b62ea7202948dec401932be66441..14148a67ab138b4e7f7efc4cc2f7eb199be1ac1d 100644 (file)
@@ -1802,6 +1802,23 @@ gui_init_fringe (struct redisplay_interface *rif)
     }
 }
 
+/* Call frame F's specific define_fringe_bitmap method for a fringe
+   bitmap number N.  Called by various *term.c functions when they
+   need to display a fringe bitmap whose terminal-specific data is not
+   available.  */
+void
+gui_define_fringe_bitmap (struct frame *f, int n)
+{
+  struct redisplay_interface *rif = FRAME_RIF (f);
+
+  if (!rif || !rif->define_fringe_bitmap || n >= max_used_fringe_bitmap)
+    return;
+
+  struct fringe_bitmap *fb = fringe_bitmaps[n];
+  if (fb)
+    rif->define_fringe_bitmap (n, fb->bits, fb->height, fb->width);
+}
+
 #ifdef HAVE_NTGUI
 void
 w32_reset_fringes (void)
index 6b41b1d324ff733168c3e98bc88c8016bf63d47f..ae99d9948e67766a09063730615ee4c191cbbec3 100644 (file)
@@ -777,12 +777,25 @@ w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
     w32_fill_area (f, hdc, face->background,
                   p->bx, p->by, p->nx, p->ny);
 
-  if (p->which && p->which < max_fringe_bmp)
+  if (p->which
+      && p->which < max_fringe_bmp
+      && p->which < max_used_fringe_bitmap)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
       HDC compat_hdc;
       HANDLE horig_obj;
 
+      if (!fringe_bmp[p->which])
+       {
+         /* This fringe bitmap is known to fringe.c, but lacks the
+            HBITMAP data which shadows that bitmap.  This is typical
+            to define-fringe-bitmap being called when the selected
+            frame was not a GUI frame, for example, when packages
+            that define fringe bitmaps are loaded by a daemon Emacs.
+            Create the missing HBITMAP now.  */
+         gui_define_fringe_bitmap (f, p->which);
+       }
+
       compat_hdc = CreateCompatibleDC (hdc);
 
       SaveDC (hdc);
index 59413eafd48e17b8a8880c71e25ae7703236f466..9a8c3e9ad76da51cc47047b5a48351b9e14c2dac 100644 (file)
@@ -1426,7 +1426,9 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
     }
 
 #ifdef USE_CAIRO
-  if (p->which && p->which < max_fringe_bmp)
+  if (p->which
+      && p->which < max_fringe_bmp
+      && p->which < max_used_fringe_bitmap)
     {
       XGCValues gcv;
 
@@ -1436,6 +1438,16 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
                                       : f->output_data.x->cursor_pixel)
                                    : face->foreground));
       XSetBackground (display, gc, face->background);
+      if (!fringe_bmp[p->which])
+       {
+         /* This fringe bitmap is known to fringe.c, but lacks the
+            cairo_pattern_t pattern which shadows that bitmap.  This
+            is typical to define-fringe-bitmap being called when the
+            selected frame was not a GUI frame, for example, when
+            packages that define fringe bitmaps are loaded by a
+            daemon Emacs.  Create the missing pattern now.  */
+         gui_define_fringe_bitmap (f, p->which);
+       }
       x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
                       p->wd, p->h, p->x, p->y, p->overlay_p);
       XSetForeground (display, gc, gcv.foreground);