Index: src/console.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/console.h,v retrieving revision 1.22.2.11 diff -u -r1.22.2.11 console.h --- src/console.h 1999/09/16 16:56:48 1.22.2.11 +++ src/console.h 1999/10/05 20:34:17 @@ -231,6 +231,7 @@ int depth); void (*init_image_instance_from_eimage_method) (struct Lisp_Image_Instance *ii, int width, int height, + int slices, unsigned char *eimage, int dest_mask, Lisp_Object instantiator, Index: src/device.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/device.h,v retrieving revision 1.8.2.4 diff -u -r1.8.2.4 device.h --- src/device.h 1999/09/23 07:39:46 1.8.2.4 +++ src/device.h 1999/10/05 20:34:19 @@ -168,6 +168,7 @@ unsigned int frame_changed :1; unsigned int glyphs_changed :1; unsigned int subwindows_changed :1; + unsigned int subwindows_state_changed :1; unsigned int icon_changed :1; unsigned int menubar_changed :1; unsigned int modeline_changed :1; @@ -348,6 +349,9 @@ #define MARK_DEVICE_SUBWINDOWS_CHANGED(d) \ ((void) (subwindows_changed = (d)->subwindows_changed = 1)) +#define MARK_DEVICE_SUBWINDOWS_STATE_CHANGED(d) \ + ((void) (subwindows_state_changed = (d)->subwindows_state_changed = 1)) + #define MARK_DEVICE_TOOLBARS_CHANGED(d) \ ((void) (toolbar_changed = (d)->toolbar_changed = 1)) @@ -363,6 +367,14 @@ DEVICE_FRAME_LOOP (frmcons, mdffc_d) \ XFRAME (XCAR (frmcons))->faces_changed = 1; \ MARK_DEVICE_FACES_CHANGED (mdffc_d); \ +} while (0) + +#define MARK_DEVICE_FRAMES_GLYPHS_CHANGED(d) do { \ + struct device *mdffc_d = (d); \ + Lisp_Object frmcons; \ + DEVICE_FRAME_LOOP (frmcons, mdffc_d) \ + XFRAME (XCAR (frmcons))->glyphs_changed = 1; \ + MARK_DEVICE_GLYPHS_CHANGED (mdffc_d); \ } while (0) #define MARK_DEVICE_FRAME_CHANGED(d) \ Index: src/frame.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/frame.h,v retrieving revision 1.18.2.5 diff -u -r1.18.2.5 frame.h --- src/frame.h 1999/09/23 07:39:52 1.18.2.5 +++ src/frame.h 1999/10/05 20:34:21 @@ -181,6 +181,7 @@ unsigned int faces_changed :1; unsigned int frame_changed :1; unsigned int subwindows_changed :1; + unsigned int subwindows_state_changed :1; unsigned int glyphs_changed :1; unsigned int icon_changed :1; unsigned int menubar_changed :1; @@ -341,6 +342,19 @@ } \ else \ subwindows_changed = 1; \ +} while (0) + +#define MARK_FRAME_SUBWINDOWS_STATE_CHANGED(f) do { \ + struct frame *mfgc_f = (f); \ + mfgc_f->subwindows_state_changed = 1; \ + mfgc_f->modiff++; \ + if (!NILP (mfgc_f->device)) \ + { \ + struct device *mfgc_d = XDEVICE (mfgc_f->device); \ + MARK_DEVICE_SUBWINDOWS_STATE_CHANGED (mfgc_d); \ + } \ + else \ + subwindows_state_changed = 1; \ } while (0) #define MARK_FRAME_TOOLBARS_CHANGED(f) do { \ Index: src/glyphs-eimage.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-eimage.c,v retrieving revision 1.3.2.5 diff -u -r1.3.2.5 glyphs-eimage.c --- src/glyphs-eimage.c 1999/01/18 22:00:18 1.3.2.5 +++ src/glyphs-eimage.c 1999/10/05 20:34:25 @@ -482,7 +482,7 @@ /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, cinfo.output_width, cinfo.output_height, + (ii, cinfo.output_width, cinfo.output_height, 1, unwind.eimage, dest_mask, instantiator, domain)); @@ -651,10 +651,10 @@ DGifSlurp (unwind.giffile); } - /* 3. Now create the EImage */ + /* 3. Now create the EImage(s) */ { ColorMapObject *cmo = unwind.giffile->SColorMap; - int i, j, row, pass, interlace; + int i, j, row, pass, interlace, slice; unsigned char *eip; /* interlaced gifs have rows in this order: 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */ @@ -663,52 +663,63 @@ height = unwind.giffile->SHeight; width = unwind.giffile->SWidth; - unwind.eimage = (unsigned char*) xmalloc (width * height * 3); + unwind.eimage = (unsigned char*) + xmalloc (width * height * 3 * unwind.giffile->ImageCount); if (!unwind.eimage) signal_image_error("Unable to allocate enough memory for image", instantiator); /* write the data in EImage format (8bit RGB triples) */ - /* Note: We just use the first image in the file and ignore the rest. - We check here that that image covers the full "screen" size. - I don't know whether that's always the case. - -dkindred@cs.cmu.edu */ - if (unwind.giffile->SavedImages[0].ImageDesc.Height != height - || unwind.giffile->SavedImages[0].ImageDesc.Width != width - || unwind.giffile->SavedImages[0].ImageDesc.Left != 0 - || unwind.giffile->SavedImages[0].ImageDesc.Top != 0) - signal_image_error ("First image in GIF file is not full size", - instantiator); - - interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace; - pass = 0; - row = interlace ? InterlacedOffset[pass] : 0; - eip = unwind.eimage; - for (i = 0; i < height; i++) + for (slice = 0; slice < unwind.giffile->ImageCount; slice++) { - if (interlace) - if (row >= height) { - row = InterlacedOffset[++pass]; - while (row >= height) - row = InterlacedOffset[++pass]; - } - eip = unwind.eimage + (row * width * 3); - for (j = 0; j < width; j++) + /* Note: We just use the first image in the file and ignore the rest. + We check here that that image covers the full "screen" size. + I don't know whether that's always the case. + -dkindred@cs.cmu.edu */ + if (unwind.giffile->SavedImages[slice].ImageDesc.Height != height + || unwind.giffile->SavedImages[slice].ImageDesc.Width != width + || unwind.giffile->SavedImages[slice].ImageDesc.Left != 0 + || unwind.giffile->SavedImages[slice].ImageDesc.Top != 0) + signal_image_error ("Image in GIF file is not full size", + instantiator); + + interlace = unwind.giffile->SavedImages[slice].ImageDesc.Interlace; + pass = 0; + row = interlace ? InterlacedOffset[pass] : 0; + eip = unwind.eimage + (width * height * 3 * slice); + for (i = 0; i < height; i++) { - unsigned char pixel = unwind.giffile->SavedImages[0].RasterBits[(i * width) + j]; - *eip++ = cmo->Colors[pixel].Red; - *eip++ = cmo->Colors[pixel].Green; - *eip++ = cmo->Colors[pixel].Blue; + if (interlace) + if (row >= height) { + row = InterlacedOffset[++pass]; + while (row >= height) + row = InterlacedOffset[++pass]; + } + eip = unwind.eimage + (width * height * 3 * slice) + (row * width * 3); + for (j = 0; j < width; j++) + { + unsigned char pixel = + unwind.giffile->SavedImages[slice].RasterBits[(i * width) + j]; + *eip++ = cmo->Colors[pixel].Red; + *eip++ = cmo->Colors[pixel].Green; + *eip++ = cmo->Colors[pixel].Blue; + } + row += interlace ? InterlacedJumps[pass] : 1; } - row += interlace ? InterlacedJumps[pass] : 1; } } /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, width, height, unwind.eimage, dest_mask, + (ii, width, height, unwind.giffile->ImageCount, unwind.eimage, dest_mask, instantiator, domain)); + /* We read the gif successfully. If we have more than one slice then + animate the gif. */ + if (unwind.giffile->ImageCount > 1) + { + add_glyph_animated_timeout (100, ii->device); + } unbind_to (speccount, Qnil); } @@ -990,7 +1001,7 @@ /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, width, height, unwind.eimage, dest_mask, + (ii, width, height, 1, unwind.eimage, dest_mask, instantiator, domain)); /* This will clean up everything else. */ @@ -1270,7 +1281,7 @@ /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, width, height, unwind.eimage, dest_mask, + (ii, width, height, 1, unwind.eimage, dest_mask, instantiator, domain)); unbind_to (speccount, Qnil); Index: src/glyphs-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.c,v retrieving revision 1.21.2.24 diff -u -r1.21.2.24 glyphs-msw.c --- src/glyphs-msw.c 1999/09/20 10:48:29 1.21.2.24 +++ src/glyphs-msw.c 1999/10/05 20:34:32 @@ -99,7 +99,8 @@ static void mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, - enum image_instance_type type); + int slices, + enum image_instance_type type); static void mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image, struct frame* f); @@ -290,6 +291,7 @@ int dest_mask, void *bmp_data, int bmp_bits, + int slices, Lisp_Object instantiator, int x_hot, int y_hot, int create_mask) @@ -331,12 +333,14 @@ /* copy in the actual bitmap */ memcpy (bmp_buf, bmp_data, bmp_bits); - mswindows_initialize_dibitmap_image_instance (ii, type); + mswindows_initialize_dibitmap_image_instance (ii, slices, type); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); + /* Fixup a set of bitmaps. */ IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap; + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL; IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = bmp_info->bmiHeader.biWidth; IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = bmp_info->bmiHeader.biHeight; @@ -356,8 +360,36 @@ } static void +image_instance_add_dibitmap (struct Lisp_Image_Instance *ii, + BITMAPINFO *bmp_info, + void *bmp_data, + int bmp_bits, + int slice, + Lisp_Object instantiator) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + struct device *d = XDEVICE (device); + struct frame *f = XFRAME (DEVICE_SELECTED_FRAME (d)); + void* bmp_buf=0; + HDC hdc = FRAME_MSWINDOWS_CDC (f); + HBITMAP bitmap = CreateDIBSection (hdc, + bmp_info, + DIB_RGB_COLORS, + &bmp_buf, + 0,0); + + if (!bitmap || !bmp_buf) + signal_simple_error ("Unable to create bitmap", instantiator); + + /* copy in the actual bitmap */ + memcpy (bmp_buf, bmp_data, bmp_bits); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (ii, slice) = bitmap; +} + +static void mswindows_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, int width, int height, + int slices, unsigned char *eimage, int dest_mask, Lisp_Object instantiator, @@ -368,6 +400,7 @@ unsigned char* bmp_data; int bmp_bits; COLORREF bkcolor; + int slice; if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) signal_simple_error ("Not an mswindows device", device); @@ -377,21 +410,29 @@ bkcolor = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (FACE_BACKGROUND (Vdefault_face, domain))); - /* build a bitmap from the eimage */ - if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage, - &bmp_bits, &bmp_data))) + for (slice = 0; slice < slices; slice++) { - signal_simple_error ("EImage to DIBitmap conversion failed", - instantiator); - } - - /* Now create the pixmap and set up the image instance */ - init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, - bmp_data, bmp_bits, instantiator, - 0, 0, 0); + /* build a bitmap from the eimage */ + if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, + eimage + (width * height * 3 * slice), + &bmp_bits, &bmp_data))) + { + signal_simple_error ("EImage to DIBitmap conversion failed", + instantiator); + } - xfree (bmp_info); - xfree (bmp_data); + /* Now create the pixmap and set up the image instance */ + if (slice == 0) + init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, + bmp_data, bmp_bits, slices, instantiator, + 0, 0, 0); + else + image_instance_add_dibitmap (ii, bmp_info, bmp_data, bmp_bits, slice, + instantiator); + + xfree (bmp_info); + xfree (bmp_data); + } } static void set_mono_pixel ( unsigned char* bits, @@ -920,7 +961,7 @@ /* Now create the pixmap and set up the image instance */ init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, - bmp_data, bmp_bits, instantiator, + bmp_data, bmp_bits, 1, instantiator, x_hot, y_hot, transp); xfree (bmp_info); @@ -983,7 +1024,7 @@ /* Now create the pixmap and set up the image instance */ init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, - bmp_data, bmp_bits, instantiator, + bmp_data, bmp_bits, 1, instantiator, 0, 0, 0); } @@ -1238,7 +1279,7 @@ if (hinst) FreeLibrary (hinst); - mswindows_initialize_dibitmap_image_instance (ii, iitype); + mswindows_initialize_dibitmap_image_instance (ii, 1, iitype); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file; IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = @@ -1720,7 +1761,7 @@ IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); - mswindows_initialize_dibitmap_image_instance (ii, type); + mswindows_initialize_dibitmap_image_instance (ii, 1, type); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); @@ -2007,9 +2048,16 @@ } else if (p->data) { - if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)) - DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)); - IMAGE_INSTANCE_MSWINDOWS_BITMAP (p) = 0; + int i; + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p)) + { + for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) + { + DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0; + } + xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p)); + } if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p)); IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0; @@ -2238,6 +2286,7 @@ static void mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, + int slices, enum image_instance_type type) { ii->data = xnew_and_zero (struct mswindows_image_instance_data); @@ -2248,6 +2297,9 @@ IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil; IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil; IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) = + xnew_array_and_zero (HBITMAP, slices); } Index: src/glyphs-msw.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.h,v retrieving revision 1.7.2.3 diff -u -r1.7.2.3 glyphs-msw.h --- src/glyphs-msw.h 1999/09/16 16:56:49 1.7.2.3 +++ src/glyphs-msw.h 1999/10/05 20:34:33 @@ -34,7 +34,7 @@ struct mswindows_image_instance_data { - HBITMAP bitmap; + HBITMAP* bitmaps; HICON icon; }; @@ -42,7 +42,11 @@ ((struct mswindows_image_instance_data *) (i)->data) #define IMAGE_INSTANCE_MSWINDOWS_BITMAP(i) \ - (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmap) + (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmaps[0]) +#define IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE(i,slice) \ + (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmaps[slice]) +#define IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES(i) \ + (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmaps) #define IMAGE_INSTANCE_MSWINDOWS_MASK(i) \ (HBITMAP)(IMAGE_INSTANCE_PIXMAP_MASK (i)) #define IMAGE_INSTANCE_MSWINDOWS_ICON(i) \ @@ -50,6 +54,10 @@ #define XIMAGE_INSTANCE_MSWINDOWS_BITMAP(i) \ IMAGE_INSTANCE_MSWINDOWS_BITMAP (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE(i,slice) \ + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (XIMAGE_INSTANCE (i,slice)) +#define XIMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES(i) \ + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_MSWINDOWS_MASK(i) \ IMAGE_INSTANCE_MSWINDOWS_MASK (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_MSWINDOWS_ICON(i) \ Index: src/glyphs-x.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.c,v retrieving revision 1.49.2.29 diff -u -r1.49.2.29 glyphs-x.c --- src/glyphs-x.c 1999/09/23 01:28:06 1.49.2.29 +++ src/glyphs-x.c 1999/10/05 20:34:40 @@ -53,7 +53,9 @@ #include "console-x.h" #include "glyphs-x.h" #include "objects-x.h" +#ifdef HAVE_WIDGETS #include "gui-x.h" +#endif #include "xmu.h" #include "buffer.h" @@ -405,8 +407,17 @@ } else { - if (IMAGE_INSTANCE_X_PIXMAP (p)) - XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p)); + int i; + if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p)) + { + for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) + { + XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i)); + IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0; + } + xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p)); + } + if (IMAGE_INSTANCE_X_MASK (p) && IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p)) XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p)); @@ -487,9 +498,13 @@ static void x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii, + int slices, enum image_instance_type type) { ii->data = xnew_and_zero (struct x_image_instance_data); + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; + IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) = + xnew_array_and_zero (Pixmap, slices); IMAGE_INSTANCE_TYPE (ii) = type; IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil; @@ -808,6 +823,7 @@ Colormap cmap, unsigned long *pixels, int npixels, + int slices, Lisp_Object instantiator) { Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); @@ -843,12 +859,14 @@ XFreeGC (dpy, gc); - x_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP); + x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); + /* Fixup a set of pixmaps. */ IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap; + IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0; IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width; IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height; @@ -859,8 +877,44 @@ } static void +image_instance_add_x_image (struct Lisp_Image_Instance *ii, + XImage *ximage, + int slice, + Lisp_Object instantiator) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + Display *dpy; + GC gc; + Drawable d; + Pixmap pixmap; + + dpy = DEVICE_X_DISPLAY (XDEVICE (device)); + d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device))); + + pixmap = XCreatePixmap (dpy, d, ximage->width, + ximage->height, ximage->depth); + if (!pixmap) + signal_simple_error ("Unable to create pixmap", instantiator); + + gc = XCreateGC (dpy, pixmap, 0, NULL); + if (!gc) + { + XFreePixmap (dpy, pixmap); + signal_simple_error ("Unable to create GC", instantiator); + } + + XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, + ximage->width, ximage->height); + + XFreeGC (dpy, gc); + + IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap; +} + +static void x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, int width, int height, + int slices, unsigned char *eimage, int dest_mask, Lisp_Object instantiator, @@ -870,29 +924,38 @@ Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device)); unsigned long *pixtbl = NULL; int npixels = 0; + int slice; XImage* ximage; - ximage = convert_EImage_to_XImage (device, width, height, eimage, - &pixtbl, &npixels); - if (!ximage) + for (slice = 0; slice < slices; slice++) { - if (pixtbl) xfree (pixtbl); - signal_image_error("EImage to XImage conversion failed", instantiator); - } + ximage = convert_EImage_to_XImage (device, width, height, + eimage + (width * height * 3 * slice), + &pixtbl, &npixels); + if (!ximage) + { + if (pixtbl) xfree (pixtbl); + signal_image_error("EImage to XImage conversion failed", instantiator); + } - /* Now create the pixmap and set up the image instance */ - init_image_instance_from_x_image (ii, ximage, dest_mask, - cmap, pixtbl, npixels, - instantiator); + /* Now create the pixmap and set up the image instance */ + if (slice == 0) + init_image_instance_from_x_image (ii, ximage, dest_mask, + cmap, pixtbl, npixels, slices, + instantiator); + else + image_instance_add_x_image (ii, ximage, slice, instantiator); - if (ximage) - { - if (ximage->data) - { - xfree (ximage->data); - ximage->data = 0; - } - XDestroyImage (ximage); + if (ximage) + { + if (ximage->data) + { + xfree (ximage->data); + ximage->data = 0; + } + XDestroyImage (ximage); + ximage = 0; + } } } @@ -967,7 +1030,7 @@ IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); - x_initialize_pixmap_image_instance (ii, type); + x_initialize_pixmap_image_instance (ii, 1, type); IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = @@ -1271,7 +1334,7 @@ visual = DEVICE_X_VISUAL (XDEVICE(device)); #endif - x_initialize_pixmap_image_instance (ii, type); + x_initialize_pixmap_image_instance (ii, 1, type); assert (!NILP (data)); @@ -1909,7 +1972,7 @@ /* #### call XQueryTextExtents() and check_pointer_sizes() here. */ - x_initialize_pixmap_image_instance (ii, IMAGE_POINTER); + x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); IMAGE_INSTANCE_X_CURSOR (ii) = XCreateGlyphCursor (dpy, source, mask, source_char, mask_char, &fg, &bg); @@ -1962,7 +2025,7 @@ if ((i = XmuCursorNameToIndex (name_ext)) == -1) signal_simple_error ("Unrecognized cursor-font name", data); - x_initialize_pixmap_image_instance (ii, IMAGE_POINTER); + x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i); foreground = find_keyword_in_vector (instantiator, Q_foreground); if (NILP (foreground)) Index: src/glyphs-x.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.h,v retrieving revision 1.4.2.5 diff -u -r1.4.2.5 glyphs-x.h --- src/glyphs-x.h 1999/09/16 16:56:50 1.4.2.5 +++ src/glyphs-x.h 1999/10/05 20:34:40 @@ -39,7 +39,7 @@ struct x_image_instance_data { - Pixmap pixmap; + Pixmap* pixmaps; Cursor cursor; /* If depth>0, then that means that other colors were allocated when @@ -55,7 +55,11 @@ #define X_IMAGE_INSTANCE_DATA(i) ((struct x_image_instance_data *) (i)->data) -#define IMAGE_INSTANCE_X_PIXMAP(i) (X_IMAGE_INSTANCE_DATA (i)->pixmap) +#define IMAGE_INSTANCE_X_PIXMAP(i) (X_IMAGE_INSTANCE_DATA (i)->pixmaps[0]) +#define IMAGE_INSTANCE_X_PIXMAP_SLICE(i,slice) \ + (X_IMAGE_INSTANCE_DATA (i)->pixmaps[slice]) +#define IMAGE_INSTANCE_X_PIXMAP_SLICES(i) \ + (X_IMAGE_INSTANCE_DATA (i)->pixmaps) #define IMAGE_INSTANCE_X_MASK(i) \ (Pixmap)(IMAGE_INSTANCE_PIXMAP_MASK (i)) #define IMAGE_INSTANCE_X_CURSOR(i) (X_IMAGE_INSTANCE_DATA (i)->cursor) @@ -65,6 +69,10 @@ #define XIMAGE_INSTANCE_X_PIXMAP(i) \ IMAGE_INSTANCE_X_PIXMAP (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_PIXMAP_SLICES(i) \ + IMAGE_INSTANCE_X_PIXMAP_SLICES (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_PIXMAP_SLICE(i) \ + IMAGE_INSTANCE_X_PIXMAP_SLICE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_MASK(i) \ IMAGE_INSTANCE_X_MASK (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_CURSOR(i) \ Index: src/glyphs.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v retrieving revision 1.23.2.28 diff -u -r1.23.2.28 glyphs.c --- src/glyphs.c 1999/09/23 07:39:59 1.23.2.28 +++ src/glyphs.c 1999/10/05 20:34:53 @@ -823,7 +823,7 @@ || IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW) { - MARK_FRAME_GLYPHS_CHANGED + MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i))); } @@ -867,6 +867,8 @@ IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) && IMAGE_INSTANCE_PIXMAP_DEPTH (i1) == IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && + IMAGE_INSTANCE_PIXMAP_SLICE (i1) == + IMAGE_INSTANCE_PIXMAP_SLICE (i2) && EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1), IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) && EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1), @@ -938,9 +940,10 @@ case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: case IMAGE_POINTER: - hash = HASH5 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), + hash = HASH6 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), IMAGE_INSTANCE_PIXMAP_HEIGHT (i), IMAGE_INSTANCE_PIXMAP_DEPTH (i), + IMAGE_INSTANCE_PIXMAP_SLICE (i), internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), depth + 1)); break; @@ -1039,7 +1042,7 @@ { /* This depends on the fact that enums are assigned consecutive integers starting at 0. (Remember that IMAGE_UNKNOWN is the - first enum.) I'm fairly sure this behavior in ANSI-mandated, + first enum.) I'm fairly sure this behavior is ANSI-mandated, so there should be no portability problems here. */ return (1 << ((int) (type) - 1)); } @@ -1366,6 +1369,10 @@ val = Qnil; } } + + /* Make sure the image instance gets redisplayed. */ + MARK_IMAGE_INSTANCE_CHANGED (ii); + return val; } @@ -3062,6 +3069,7 @@ g->type = type; g->image = Fmake_specifier (Qimage); /* This function can GC */ + g->dirty = 0; switch (g->type) { case GLYPH_BUFFER: @@ -3218,16 +3226,16 @@ the given FACE, unless a face is defined by the glyph itself. ****************************************************************************/ unsigned short -glyph_width (Lisp_Object glyph, Lisp_Object frame_face, +glyph_width (Lisp_Object glyph_or_image, Lisp_Object frame_face, face_index window_findex, Lisp_Object window) { - Lisp_Object instance = glyph; + Lisp_Object instance = glyph_or_image; Lisp_Object frame = XWINDOW (window)->frame; /* #### We somehow need to distinguish between the user causing this error condition and a bug causing it. */ - if (GLYPHP (glyph)) - instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); if (!IMAGE_INSTANCEP (instance)) return 0; @@ -3239,8 +3247,8 @@ Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance); Lisp_Object private_face = Qnil; - if (GLYPHP (glyph)) - private_face = XGLYPH_FACE(glyph); + if (GLYPHP (glyph_or_image)) + private_face = XGLYPH_FACE(glyph_or_image); if (!NILP (private_face)) return redisplay_frame_text_width_string (XFRAME (frame), @@ -3306,15 +3314,15 @@ } static unsigned short -glyph_height_internal (Lisp_Object glyph, Lisp_Object frame_face, +glyph_height_internal (Lisp_Object glyph_or_image, Lisp_Object frame_face, face_index window_findex, Lisp_Object window, int function) { - Lisp_Object instance = glyph; + Lisp_Object instance = glyph_or_image; Lisp_Object frame = XWINDOW (window)->frame; - if (GLYPHP (glyph)) - instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); if (!IMAGE_INSTANCEP (instance)) return 0; @@ -3452,6 +3460,35 @@ #undef RETURN_DESCENT #undef RETURN_HEIGHT +static unsigned int +glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window) +{ + Lisp_Object instance = glyph_or_image; + + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); + + return XIMAGE_INSTANCE_DIRTYP (instance); +} + +static void +set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty) +{ + Lisp_Object instance = glyph_or_image; + + if (!NILP (glyph_or_image)) + { + if (GLYPHP (glyph_or_image)) + { + instance = glyph_image_instance (glyph_or_image, window, + ERROR_ME_NOT, 1); + XGLYPH_DIRTYP (glyph_or_image) = dirty; + } + + XIMAGE_INSTANCE_DIRTYP (instance) = dirty; + } +} + /* #### do we need to cache this info to speed things up? */ Lisp_Object @@ -3514,7 +3551,6 @@ /* #### All of this is 95% copied from face cachels. Consider consolidating. - #### We need to add a dirty flag to the glyphs. */ void @@ -3537,19 +3573,21 @@ update_glyph_cachel_data (struct window *w, Lisp_Object glyph, struct glyph_cachel *cachel) { - /* #### This should be || !cachel->updated */ - if (NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)) + if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph) + || XGLYPH_DIRTYP (cachel->glyph)) { - Lisp_Object window; + Lisp_Object window, instance; XSETWINDOW (window, w); - /* #### This could be sped up if we redid things to grab the glyph - instantiation and passed it to the size functions. */ cachel->glyph = glyph; - cachel->width = glyph_width (glyph, Qnil, DEFAULT_INDEX, window); - cachel->ascent = glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window); - cachel->descent = glyph_descent (glyph, Qnil, DEFAULT_INDEX, window); + /* Speed things up slightly by grabbing the glyph instantiation + and passing it to the size functions. */ + instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window); + cachel->width = glyph_width (instance, Qnil, DEFAULT_INDEX, window); + cachel->ascent = glyph_ascent (instance, Qnil, DEFAULT_INDEX, window); + cachel->descent = glyph_descent (instance, Qnil, DEFAULT_INDEX, window); } cachel->updated = 1; @@ -3567,7 +3605,7 @@ Dynarr_add (w->glyph_cachels, new_cachel); } -static glyph_index +glyph_index get_glyph_cachel_index (struct window *w, Lisp_Object glyph) { int elt; @@ -3582,8 +3620,7 @@ if (EQ (cachel->glyph, glyph) && !NILP (glyph)) { - if (!cachel->updated) - update_glyph_cachel_data (w, glyph, cachel); + update_glyph_cachel_data (w, glyph, cachel); return elt; } } @@ -3625,8 +3662,25 @@ FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX); #undef FROB + for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) + { + Dynarr_atp (w->glyph_cachels, elt)->updated = 0; + } +} + +/* Unset the dirty bit on all the glyph cachels that have it. */ +void +mark_glyph_cachels_as_clean (struct window* w) +{ + int elt; + Lisp_Object window; + XSETWINDOW (window, w); for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) - Dynarr_atp (w->glyph_cachels, elt)->updated = 0; + { + struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt); + cachel->dirty = 0; + set_glyph_dirty_p (cachel->glyph, window, 0); + } } #ifdef MEMORY_USAGE_STATS @@ -3928,7 +3982,7 @@ { int elt; - if (f->subwindows_changed || f->glyphs_changed || f->faces_changed) + if (f->subwindows_changed || f->subwindows_state_changed || f->faces_changed) for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) { struct subwindow_cachel *cachel = @@ -4204,6 +4258,80 @@ } } +/***************************************************************************** + * timeouts for animated glyphs * + *****************************************************************************/ +static Lisp_Object Qglyph_animated_timeout_handler; +static Lisp_Object Vglyph_animated_ticker; + +static int glyph_animated_timeout_mapper (Lisp_Object key, Lisp_Object value, + void* extra_arg) +{ + if (IMAGE_INSTANCEP (value)) + { + struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value); + if (COLOR_PIXMAP_IMAGE_INSTANCEP (value) + && + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1) + { + /* Increment the index of the image slice we are currently + viewing. */ + IMAGE_INSTANCE_PIXMAP_SLICE (ii) = + (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1) + % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii); + /* We might need to kick redisplay at this point - but we + also might not. */ + MARK_DEVICE_FRAMES_GLYPHS_CHANGED + (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))); + IMAGE_INSTANCE_DIRTYP (ii) = 1; + } + } + return 0; +} + +DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /* +Callback function for updating animated images. +Don't use this. +*/ + (arg)) +{ + struct device* d; + Lisp_Object hasht; + + CHECK_DEVICE (arg); + d = XDEVICE (arg); + + hasht = Fgethash + ( make_int (IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK + | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK + | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK + | IMAGE_LAYOUT_MASK ), + d->image_instance_cache, Qunbound); + + if (!UNBOUNDP (hasht)) + elisp_maphash ((maphash_function_t)&glyph_animated_timeout_mapper, + hasht, 0); + return Qnil; +} + +void add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object device) +{ + if (tickms > 0) + { + double ms = ((double)tickms) / 1000.0; + Vglyph_animated_ticker = Fadd_timeout (make_float (ms), + Qglyph_animated_timeout_handler, + device, make_float (ms)); + } +} +void disable_glyph_animated_timeout () +{ + if (!NILP (Vglyph_animated_ticker)) + { + Fdisable_timeout (Vglyph_animated_ticker); + } +} + /***************************************************************************** * initialization * @@ -4311,6 +4439,12 @@ /* Qbuffer defined in general.c. */ /* Qpointer defined above */ + /* Unfortunately, timeout handlers must be lisp functions. This is + for animated glyphs. */ + defsymbol (&Qglyph_animated_timeout_handler, + "glyph-animated-timeout-handler"); + DEFSUBR (Fglyph_animated_timeout_handler); + /* Errors */ deferror (&Qimage_conversion_error, "image-conversion-error", @@ -4505,6 +4639,10 @@ Fprovide (Qxface); #endif hold_ignored_expose_registration = 0; + + /* For animated glyphs. */ + Vglyph_animated_ticker = Qnil; + staticpro (&Vglyph_animated_ticker); } void Index: src/glyphs.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.h,v retrieving revision 1.18.2.17 diff -u -r1.18.2.17 glyphs.h --- src/glyphs.h 1999/09/16 16:56:50 1.18.2.17 +++ src/glyphs.h 1999/10/05 20:34:55 @@ -442,6 +442,7 @@ Lisp_Object name; enum image_instance_type type; int x_offset, y_offset; /* for layout purposes */ + unsigned int dirty : 1; union { struct @@ -451,6 +452,7 @@ struct { int width, height, depth; + int slice, maxslice, timeout; Lisp_Object hotspot_x, hotspot_y; /* integer or Qnil */ Lisp_Object filename; /* string or Qnil */ Lisp_Object mask_filename; /* string or Qnil */ @@ -466,7 +468,7 @@ Lisp_Object frame; unsigned int width, height; void* subwindow; /* specific devices can use this as necessary */ - int being_displayed; /* used to detect when needs to be unmapped */ + unsigned int being_displayed : 1; /* used to detect when needs to be unmapped */ union { struct @@ -497,6 +499,7 @@ #define IMAGE_INSTANCE_PIXMAP_TYPE_P(i) \ ((IMAGE_INSTANCE_TYPE (i) == IMAGE_MONO_PIXMAP) \ || (IMAGE_INSTANCE_TYPE (i) == IMAGE_COLOR_PIXMAP)) +#define IMAGE_INSTANCE_DIRTYP(i) ((i)->dirty) #define IMAGE_INSTANCE_TEXT_STRING(i) ((i)->u.text.string) @@ -511,6 +514,9 @@ #define IMAGE_INSTANCE_PIXMAP_BG(i) ((i)->u.pixmap.bg) #define IMAGE_INSTANCE_PIXMAP_AUXDATA(i) ((i)->u.pixmap.auxdata) #define IMAGE_INSTANCE_PIXMAP_MASK(i) ((i)->u.pixmap.mask) +#define IMAGE_INSTANCE_PIXMAP_SLICE(i) ((i)->u.pixmap.slice) +#define IMAGE_INSTANCE_PIXMAP_MAXSLICE(i) ((i)->u.pixmap.maxslice) +#define IMAGE_INSTANCE_PIXMAP_TIMEOUT(i) ((i)->u.pixmap.timeout) #define IMAGE_INSTANCE_SUBWINDOW_WIDTH(i) ((i)->u.subwindow.width) #define IMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) ((i)->u.subwindow.height) @@ -546,6 +552,8 @@ IMAGE_INSTANCE_XOFFSET (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_YOFFSET(i) \ IMAGE_INSTANCE_YOFFSET (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_DIRTYP(i) \ + IMAGE_INSTANCE_DIRTYP (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_TEXT_STRING(i) \ IMAGE_INSTANCE_TEXT_STRING (XIMAGE_INSTANCE (i)) @@ -570,6 +578,12 @@ IMAGE_INSTANCE_PIXMAP_BG (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_PIXMAP_MASK(i) \ IMAGE_INSTANCE_PIXMAP_MASK (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_SLICE(i) \ + IMAGE_INSTANCE_PIXMAP_SLICE (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_MAXSLICE(i) \ + IMAGE_INSTANCE_PIXMAP_MAXSLICE (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_TIMEOUT(i) \ + IMAGE_INSTANCE_PIXMAP_TIMEOUT (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_WIDTH(i) \ IMAGE_INSTANCE_WIDGET_WIDTH (XIMAGE_INSTANCE (i)) @@ -604,6 +618,9 @@ #define XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(i) \ IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (XIMAGE_INSTANCE (i)) +#define MARK_IMAGE_INSTANCE_CHANGED(i) \ + (IMAGE_INSTANCE_DIRTYP (i) = 1); + #ifdef HAVE_XPM Lisp_Object evaluate_xpm_color_symbols (void); Lisp_Object pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid); @@ -643,10 +660,13 @@ Lisp_Object baseline; /* percent above baseline */ Lisp_Object face; /* if non-nil, face to use when displaying */ - + Lisp_Object plist; void (*after_change) (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale); + + unsigned int dirty : 1; /* So that we can selectively + redisplay changed glyphs. */ }; DECLARE_LRECORD (glyph, struct Lisp_Glyph); @@ -680,13 +700,17 @@ #define GLYPH_CONTRIB_P(g) ((g)->contrib_p) #define GLYPH_BASELINE(g) ((g)->baseline) #define GLYPH_FACE(g) ((g)->face) +#define GLYPH_DIRTYP(g) ((g)->dirty) #define XGLYPH_TYPE(g) GLYPH_TYPE (XGLYPH (g)) #define XGLYPH_IMAGE(g) GLYPH_IMAGE (XGLYPH (g)) #define XGLYPH_CONTRIB_P(g) GLYPH_CONTRIB_P (XGLYPH (g)) #define XGLYPH_BASELINE(g) GLYPH_BASELINE (XGLYPH (g)) #define XGLYPH_FACE(g) GLYPH_FACE (XGLYPH (g)) +#define XGLYPH_DIRTYP(g) GLYPH_DIRTYP (XGLYPH (g)) +#define MARK_GLYPH_CHANGED(g) (GLYPH_DIRTYP (g) = 1); + extern Lisp_Object Qxpm, Qxface, Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; extern Lisp_Object Q_data, Q_file, Q_color_symbols, Qconst_glyph_variable; extern Lisp_Object Qxbm, Qedit_field, Qgroup, Qlabel, Qcombo_box, Qscrollbar; @@ -736,6 +760,7 @@ void widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face, int th, int tw, int* height, int* width); +void add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object device); /************************************************************************/ /* Glyph Cachels */ @@ -746,7 +771,14 @@ { Lisp_Object glyph; + unsigned int dirty :1; /* I'm copying faces here. I'm not + sure why we need two dirty + flags. Maybe because an image + instance can be dirty and so we + need to frob this in the same way + as other image instance properties. */ unsigned int updated :1; + unsigned short width; unsigned short ascent; unsigned short descent; @@ -769,11 +801,15 @@ Dynarr_atp (window->glyph_cachels, index)->ascent #define GLYPH_CACHEL_DESCENT(window, index) \ Dynarr_atp (window->glyph_cachels, index)->descent +#define GLYPH_CACHEL_DIRTYP(window, index) \ + Dynarr_atp (window->glyph_cachels, index)->dirty void mark_glyph_cachels (glyph_cachel_dynarr *elements, void (*markobj) (Lisp_Object)); void mark_glyph_cachels_as_not_updated (struct window *w); +void mark_glyph_cachels_as_clean (struct window *w); void reset_glyph_cachels (struct window *w); +glyph_index get_glyph_cachel_index (struct window *w, Lisp_Object glyph); #ifdef MEMORY_USAGE_STATS int compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels, @@ -800,8 +836,8 @@ Lisp_Object subwindow; int x, y; int width, height; - int being_displayed; - int updated; + unsigned int being_displayed : 1; + unsigned int updated : 1; }; typedef struct Index: src/gui-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/gui-msw.c,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 gui-msw.c --- src/gui-msw.c 1998/12/18 05:42:10 1.1.2.1 +++ src/gui-msw.c 1999/10/05 20:34:55 @@ -46,7 +46,7 @@ if (NILP (data) || UNBOUNDP (data)) return Qnil; - MARK_SUBWINDOWS_CHANGED; + MARK_SUBWINDOWS_STATE_CHANGED; /* Ok, this is our one. Enqueue it. */ get_gui_callback (data, &fn, &arg); XSETFRAME (frame, f); Index: src/gui-x.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui-x.c,v retrieving revision 1.14.2.10 diff -u -r1.14.2.10 gui-x.c --- src/gui-x.c 1999/08/17 08:35:32 1.14.2.10 +++ src/gui-x.c 1999/10/05 20:34:57 @@ -257,7 +257,7 @@ } else { - MARK_SUBWINDOWS_CHANGED; + MARK_SUBWINDOWS_STATE_CHANGED; get_gui_callback (data, &fn, &arg); } @@ -637,8 +637,9 @@ { lwlib_id_tick = (1<<16); /* start big, to not conflict with Energize */ +#ifdef HAVE_POPUPS popup_up_p = 0; - +#endif Vpopup_callbacks = Qnil; staticpro (&Vpopup_callbacks); Index: src/gutter.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/gutter.c,v retrieving revision 1.1.2.12 diff -u -r1.1.2.12 gutter.c --- src/gutter.c 1999/09/23 05:57:03 1.1.2.12 +++ src/gutter.c 1999/10/05 20:35:00 @@ -334,7 +334,8 @@ void update_frame_gutters (struct frame *f) { - if (f->gutter_changed || f->frame_changed || f->clear || f->glyphs_changed) + if (f->gutter_changed || f->frame_changed || f->clear + || f->glyphs_changed || f->windows_changed) { enum gutter_pos pos; /* and output */ Index: src/redisplay-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay-msw.c,v retrieving revision 1.28.2.8 diff -u -r1.28.2.8 redisplay-msw.c --- src/redisplay-msw.c 1999/09/03 04:38:08 1.28.2.8 +++ src/redisplay-msw.c 1999/10/05 20:35:04 @@ -609,9 +609,10 @@ SelectObject (FRAME_MSWINDOWS_CDC (f), old); } - /* now blt the bitmap itself. */ + /* Now blt the bitmap itself, or one of its slices. */ old = SelectObject (FRAME_MSWINDOWS_CDC (f), - IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE + (p, IMAGE_INSTANCE_PIXMAP_SLICE (p))); BitBlt (hdc, db->xpos, db->ypos, Index: src/redisplay-output.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay-output.c,v retrieving revision 1.11.2.17 diff -u -r1.11.2.17 redisplay-output.c --- src/redisplay-output.c 1999/09/24 12:59:27 1.11.2.17 +++ src/redisplay-output.c 1999/10/05 20:35:10 @@ -200,15 +200,28 @@ else if (crb->type == RUNE_CHAR && (crb->object.chr.ch != drb->object.chr.ch)) return 0; - else if (crb->type == RUNE_DGLYPH && - (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || - !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || - crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) - return 0; else if (crb->type == RUNE_HLINE && (crb->object.hline.thickness != drb->object.hline.thickness || crb->object.hline.yoffset != drb->object.hline.yoffset)) return 0; + else if (crb->type == RUNE_DGLYPH && + (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || + !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || + crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) + return 0; + /* Only check dirtiness if we know something has changed. */ + else if (crb->type == RUNE_DGLYPH && + XFRAME (w->frame)->glyphs_changed) + { + glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph); + /* Although doing the cachel lookup for every comparison is + very expensive.we have to do it to make sure the cache is + up-to-date. */ + if (GLYPH_CACHEL_DIRTYP (w, gindex)) + return 0; + else + return 1; + } else return 1; } @@ -360,8 +373,14 @@ force = 1; if (f->windows_structure_changed || + /* #### Why is this so? We have face cachels so that we don't + have to recalculate all the display blocks when faces + change. I have fixed this for glyphs and am inclined to think + that faces should "Just Work", but I'm not feeling brave + today. Maybe its because the face cachels represent merged + faces rather than simply instantiations in a particular + domain. */ f->faces_changed || - f->glyphs_changed || cdl->ypos != ddl->ypos || cdl->ascent != ddl->ascent || cdl->descent != ddl->descent || Index: src/redisplay-x.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay-x.c,v retrieving revision 1.23.2.14 diff -u -r1.23.2.14 redisplay-x.c --- src/redisplay-x.c 1999/09/23 07:40:07 1.23.2.14 +++ src/redisplay-x.c 1999/10/05 20:35:15 @@ -1216,13 +1216,16 @@ pixel values, instead of symbolic of fg/bg. */ if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0) { - XCopyArea (dpy, IMAGE_INSTANCE_X_PIXMAP (p), x_win, gc, xoffset, + XCopyArea (dpy, + IMAGE_INSTANCE_X_PIXMAP_SLICE + (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, xoffset, yoffset, width, height, x, y); } else { - XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), x_win, gc, + XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE + (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, xoffset, yoffset, width, height, x, y, 1L); } } Index: src/redisplay.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay.c,v retrieving revision 1.55.2.15 diff -u -r1.55.2.15 redisplay.c --- src/redisplay.c 1999/09/23 05:57:04 1.55.2.15 +++ src/redisplay.c 1999/10/05 20:35:40 @@ -378,6 +378,11 @@ int subwindows_changed; int subwindows_changed_set; +/* non-zero if any displayed subwindow is in need of updating + somewhere. */ +int subwindows_state_changed; +int subwindows_state_changed_set; + /* This variable is 1 if the icon has to be updated. It is set to 1 when `frame-icon-glyph' changes. */ int icon_changed; @@ -4240,8 +4245,10 @@ struct frame *f = XFRAME (w->frame); /* Note that a lot of the buffer controlled stuff has been left in because you might well want to make use of it (selective display - etc), its just the buffer text that we do not use. */ - struct buffer *b = XBUFFER (w->buffer); + etc), its just the buffer text that we do not use. However, it + seems to be possible for buffer to be nil sometimes so protect + against this case. */ + struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; struct device *d = XDEVICE (f->device); struct Lisp_String* s = XSTRING (disp_string); @@ -4302,10 +4309,10 @@ Since more than one display table is possible, you have great flexibility in mapping ranges of characters. */ - Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) + Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) ? XCHAR_OR_CHAR_INT (b->ctl_arrow) : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) - ? 255 : 160)); + ? 255 : 160)) : 255; Lisp_Object face_dt, window_dt; @@ -4843,7 +4850,7 @@ dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1; if (truncate_win) data.dl->num_chars = - string_column_at_point (s, dl->end_bufpos, XINT (b->tab_width)); + string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8); else /* This doesn't correctly take into account tabs and control characters but if the window isn't being truncated then this @@ -5889,10 +5896,11 @@ else mark_face_cachels_as_not_updated (w); - /* Ditto the glyph cache elements. */ + /* Ditto the glyph cache elements, although we do *not* invalidate + the cache purely because glyphs have changed - this is now + handled by the dirty flag.*/ if ((!echo_active && b != window_display_buffer (w)) - || !Dynarr_length (w->glyph_cachels) - || f->glyphs_changed) + || !Dynarr_length (w->glyph_cachels)) reset_glyph_cachels (w); else mark_glyph_cachels_as_not_updated (w); @@ -5978,6 +5986,7 @@ && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed + && !f->subwindows_state_changed && !f->point_changed && !f->windows_structure_changed) { @@ -5999,6 +6008,7 @@ && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed + && !f->subwindows_state_changed && !f->windows_structure_changed) { if (point_visible (w, pointm, CURRENT_DISP) @@ -6057,6 +6067,7 @@ && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed + && !f->subwindows_state_changed && !f->windows_structure_changed && !f->frame_changed && !truncation_changed @@ -6153,6 +6164,10 @@ somewhere else once tty updates occur on a per-frame basis. */ mark_face_cachels_as_clean (w); + /* The glyph cachels only get dirty if someone changed something. */ + if (glyphs_changed) + mark_glyph_cachels_as_clean (w); + w->windows_changed = 0; } @@ -6288,14 +6303,14 @@ if (f->clear) f->frame_changed = 1; - /* invalidate the subwindow cache. we are going to reuse the glyphs - flag here to cause subwindows to get instantiated. This is - because subwindows changed is less strict - dealing with things + /* invalidate the subwindow cache. We use subwindows_changed here to + cause subwindows to get instantiated. This is because + subwindows_state_changed is less strict - dealing with things like the clicked state of button. We have to do this before redisplaying the gutters as subwindows get unmapped in the process.*/ if (!Dynarr_length (f->subwindow_cachels) - || f->glyphs_changed + || f->subwindows_changed || f->frame_changed) { reset_subwindow_cachels (f); @@ -6361,6 +6376,7 @@ f->frame_changed = 0; f->glyphs_changed = 0; f->subwindows_changed = 0; + f->subwindows_state_changed = 0; f->icon_changed = 0; f->menubar_changed = 0; f->modeline_changed = 0; @@ -6426,7 +6442,8 @@ f->modeline_changed || f->point_changed || f->size_changed || f->toolbar_changed || f->windows_changed || f->size_slipped || f->windows_structure_changed || f->glyphs_changed || - f->subwindows_changed || f->gutter_changed) + f->subwindows_changed || f->subwindows_state_changed || + f->gutter_changed) { preempted = redisplay_frame (f, 0); } @@ -6461,7 +6478,8 @@ f->modeline_changed || f->point_changed || f->size_changed || f->toolbar_changed || f->windows_changed || f->windows_structure_changed || f->gutter_changed || - f->glyphs_changed || f->subwindows_changed) + f->glyphs_changed || f->subwindows_changed || + f->subwindows_state_changed) { preempted = redisplay_frame (f, 0); } @@ -6483,6 +6501,7 @@ d->frame_changed = 0; d->glyphs_changed = 0; d->subwindows_changed = 0; + d->subwindows_state_changed = 0; d->icon_changed = 0; d->menubar_changed = 0; d->modeline_changed = 0; @@ -6530,6 +6549,7 @@ !menubar_changed && !modeline_changed && !point_changed && !size_changed && !toolbar_changed && !windows_changed && !glyphs_changed && !subwindows_changed && + !subwindows_state_changed && !gutter_changed && !windows_structure_changed && !disable_preemption && preemption_count < max_preempts) goto done; @@ -6544,7 +6564,8 @@ d->menubar_changed || d->modeline_changed || d->point_changed || d->size_changed || d->toolbar_changed || d->windows_changed || d->windows_structure_changed || d->gutter_changed || - d->glyphs_changed || d->subwindows_changed) + d->glyphs_changed || d->subwindows_changed || + d->subwindows_state_changed) { preempted = redisplay_device (d); @@ -6569,6 +6590,7 @@ frame_changed = 0; glyphs_changed = 0; subwindows_changed = 0; + subwindows_state_changed = 0; icon_changed = 0; menubar_changed = 0; modeline_changed = 0; @@ -8989,6 +9011,8 @@ return 0; } +/* This is called if the built-in glyphs have their properties + changed. */ void redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale) Index: src/redisplay.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay.h,v retrieving revision 1.7.2.9 diff -u -r1.7.2.9 redisplay.h --- src/redisplay.h 1999/09/23 01:28:04 1.7.2.9 +++ src/redisplay.h 1999/10/05 20:35:43 @@ -428,6 +428,11 @@ extern int subwindows_changed; extern int subwindows_changed_set; +/* True if any displayed subwindow is in need of updating + somewhere. */ +extern int subwindows_state_changed; +extern int subwindows_state_changed_set; + /* True if an icon is in need of updating somewhere. */ extern int icon_changed; extern int icon_changed_set; @@ -501,6 +506,8 @@ #define MARK_GUTTER_CHANGED MARK_TYPE_CHANGED (gutter) #define MARK_GLYPHS_CHANGED MARK_TYPE_CHANGED (glyphs) #define MARK_SUBWINDOWS_CHANGED MARK_TYPE_CHANGED (subwindows) +#define MARK_SUBWINDOWS_STATE_CHANGED \ + MARK_TYPE_CHANGED (subwindows_state) /* Anytime a console, device or frame is added or deleted we need to reset these flags. */ @@ -516,7 +523,8 @@ toolbar_changed_set = 0; \ gutter_changed_set = 0; \ glyphs_changed_set = 0; \ - subwindows_changed_set = 0; \ + subwindows_changed_set = 0; \ + subwindows_state_changed_set = 0; \ } while (0) Index: tests/glyph-test.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/tests/Attic/glyph-test.el,v retrieving revision 1.1.2.14 diff -u -r1.1.2.14 glyph-test.el --- tests/glyph-test.el 1999/09/07 14:48:24 1.1.2.14 +++ tests/glyph-test.el 1999/10/05 20:35:45 @@ -1,5 +1,9 @@ (set-extent-begin-glyph (make-extent (point) (point)) + (setq im (make-glyph [gif :file "anim.gif"]))) + +(set-extent-begin-glyph + (make-extent (point) (point)) (setq im (make-glyph [xpm :file "xemacs-icon.xpm"]))) (defun foo ()