Mercurial > hg > xemacs-beta
annotate src/glyphs-gtk.c @ 5589:851c741a15d0 pkg-docs
Close branch.
| author | Stephen J. Turnbull <stephen@xemacs.org> |
|---|---|
| date | Sat, 29 Oct 2011 17:08:25 +0900 |
| parents | 1bf48c59700e |
| children | a1dd514df5c6 |
| rev | line source |
|---|---|
| 714 | 1 /* GTK-specific Lisp objects. |
| 462 | 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. |
| 3 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
| 4 Copyright (C) 1995 Tinker Systems | |
| 2959 | 5 Copyright (C) 1995, 1996, 2001, 2002, 2004, 2005 Ben Wing |
| 462 | 6 Copyright (C) 1995 Sun Microsystems |
| 7 | |
| 8 This file is part of XEmacs. | |
| 9 | |
| 10 XEmacs is free software; you can redistribute it and/or modify it | |
| 11 under the terms of the GNU General Public License as published by the | |
| 12 Free Software Foundation; either version 2, or (at your option) any | |
| 13 later version. | |
| 14 | |
| 15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
| 16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 18 for more details. | |
| 19 | |
| 20 You should have received a copy of the GNU General Public License | |
| 21 along with XEmacs; see the file COPYING. If not, write to | |
| 22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 23 Boston, MA 02111-1307, USA. */ | |
| 24 | |
| 25 /* Synched up with: Not in FSF. */ | |
| 26 | |
| 27 /* Original author: Jamie Zawinski for 19.8 | |
| 28 font-truename stuff added by Jamie Zawinski for 19.10 | |
| 29 subwindow support added by Chuck Thompson | |
| 30 additional XPM support added by Chuck Thompson | |
| 31 initial X-Face support added by Stig | |
| 32 rewritten/restructured by Ben Wing for 19.12/19.13 | |
| 33 GIF/JPEG support added by Ben Wing for 19.14 | |
| 34 PNG support added by Bill Perry for 19.14 | |
| 35 Improved GIF/JPEG support added by Bill Perry for 19.14 | |
| 36 Cleanup/simplification of error handling by Ben Wing for 19.14 | |
| 37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14 | |
| 38 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0 | |
| 39 Many changes for color work and optimizations by Jareth Hein for 21.0 | |
| 40 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0 | |
| 41 TIFF code by Jareth Hein for 21.0 | |
| 42 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c for 21.0 | |
| 43 Gtk version by William Perry for 21.1 | |
| 44 | |
| 45 TODO: | |
| 46 Support the GrayScale, StaticColor and StaticGray visual classes. | |
| 47 Convert images.el to C and stick it in here? | |
| 48 */ | |
| 49 | |
| 50 #include <config.h> | |
| 51 #include "lisp.h" | |
| 52 | |
| 53 #include "buffer.h" | |
| 872 | 54 #include "device-impl.h" |
| 55 #include "faces.h" | |
| 56 #include "file-coding.h" | |
| 57 #include "frame-impl.h" | |
| 58 #include "glyphs.h" | |
| 809 | 59 #include "gui.h" |
| 872 | 60 #include "imgproc.h" |
| 462 | 61 #include "insdel.h" |
| 872 | 62 #include "lstream.h" |
| 462 | 63 #include "opaque.h" |
| 872 | 64 #include "window.h" |
| 2168 | 65 #include "elhash.h" |
| 66 #include "events.h" | |
| 872 | 67 |
| 68 #include "console-gtk-impl.h" | |
| 69 #include "glyphs-gtk.h" | |
| 70 #include "objects-gtk-impl.h" | |
| 71 #include "ui-gtk.h" | |
| 462 | 72 |
| 73 #include "sysfile.h" | |
| 74 | |
| 75 #include <setjmp.h> | |
| 76 | |
| 2082 | 77 #if defined (HAVE_XPM) |
| 78 #include <X11/xpm.h> | |
| 79 #endif | |
| 80 | |
| 2168 | 81 /* Widget callback hash table callback slot. */ |
| 82 #define WIDGET_GLYPH_SLOT 0 | |
| 83 | |
| 462 | 84 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); |
| 85 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); | |
| 86 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); | |
| 87 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); | |
| 88 #ifdef HAVE_JPEG | |
| 89 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); | |
| 90 #endif | |
| 91 #ifdef HAVE_TIFF | |
| 92 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff); | |
| 93 #endif | |
| 94 #ifdef HAVE_PNG | |
| 95 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png); | |
| 96 #endif | |
| 97 #ifdef HAVE_GIF | |
| 98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif); | |
| 99 #endif | |
| 100 | |
| 101 #ifdef HAVE_XFACE | |
| 102 DEFINE_DEVICE_IIFORMAT (gtk, xface); | |
| 103 #endif | |
| 104 | |
| 105 #ifdef HAVE_XPM | |
| 106 DEFINE_DEVICE_IIFORMAT (gtk, xpm); | |
| 107 #endif | |
| 108 | |
| 109 DEFINE_DEVICE_IIFORMAT (gtk, xbm); | |
| 110 DEFINE_DEVICE_IIFORMAT (gtk, subwindow); | |
| 111 | |
| 112 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); | |
| 113 Lisp_Object Qcursor_font; | |
| 114 | |
| 115 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font); | |
| 116 | |
| 117 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect); | |
| 118 | |
| 119 #ifdef HAVE_WIDGETS | |
| 120 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); | |
| 121 DEFINE_DEVICE_IIFORMAT (gtk, widget); | |
| 122 DEFINE_DEVICE_IIFORMAT (gtk, native_layout); | |
| 123 DEFINE_DEVICE_IIFORMAT (gtk, button); | |
| 124 DEFINE_DEVICE_IIFORMAT (gtk, progress_gauge); | |
| 125 DEFINE_DEVICE_IIFORMAT (gtk, edit_field); | |
| 126 DEFINE_DEVICE_IIFORMAT (gtk, combo_box); | |
| 127 DEFINE_DEVICE_IIFORMAT (gtk, tab_control); | |
| 128 DEFINE_DEVICE_IIFORMAT (gtk, label); | |
| 129 #endif | |
| 130 | |
| 131 static void update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii, | |
| 132 Lisp_Object domain); | |
| 133 static void cursor_font_instantiate (Lisp_Object image_instance, | |
| 134 Lisp_Object instantiator, | |
| 135 Lisp_Object pointer_fg, | |
| 136 Lisp_Object pointer_bg, | |
| 137 int dest_mask, | |
| 138 Lisp_Object domain); | |
| 139 | |
| 2054 | 140 static GdkCursorType cursor_name_to_index (const char *name); |
| 462 | 141 |
| 142 #ifndef BitmapSuccess | |
| 143 #define BitmapSuccess 0 | |
| 144 #define BitmapOpenFailed 1 | |
| 145 #define BitmapFileInvalid 2 | |
| 146 #define BitmapNoMemory 3 | |
| 147 #endif | |
| 148 | |
| 149 #include "bitmaps.h" | |
| 150 | |
| 151 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource); | |
| 152 Lisp_Object Qgtk_resource; | |
| 153 #ifdef HAVE_WIDGETS | |
| 154 Lisp_Object Qgtk_widget_instantiate_internal, Qgtk_widget_property_internal; | |
| 155 Lisp_Object Qgtk_widget_redisplay_internal, Qgtk_widget_set_style; | |
| 156 #endif | |
| 157 | |
| 158 | |
| 159 /************************************************************************/ | |
| 160 /* image instance methods */ | |
| 161 /************************************************************************/ | |
| 162 | |
| 163 /************************************************************************/ | |
| 164 /* convert from a series of RGB triples to an XImage formated for the */ | |
| 4252 | 165 /* proper display */ |
| 462 | 166 /************************************************************************/ |
| 167 static GdkImage * | |
| 168 convert_EImage_to_GDKImage (Lisp_Object device, int width, int height, | |
| 169 unsigned char *pic, unsigned long **pixtbl, | |
| 170 int *npixels) | |
| 171 { | |
| 172 GdkColormap *cmap; | |
| 173 GdkVisual *vis; | |
| 174 GdkImage *outimg; | |
| 175 int depth, byte_cnt, i, j; | |
| 176 int rd,gr,bl,q; | |
| 177 unsigned char *data, *ip, *dp = NULL; | |
| 178 quant_table *qtable = NULL; | |
| 179 union { | |
| 826 | 180 UINT_32_BIT val; |
| 462 | 181 char cp[4]; |
| 182 } conv; | |
| 183 | |
| 184 cmap = DEVICE_GTK_COLORMAP (XDEVICE(device)); | |
| 185 vis = DEVICE_GTK_VISUAL (XDEVICE(device)); | |
| 186 depth = DEVICE_GTK_DEPTH(XDEVICE(device)); | |
| 187 | |
| 188 if (vis->type == GDK_VISUAL_GRAYSCALE || vis->type == GDK_VISUAL_STATIC_COLOR || | |
| 189 vis->type == GDK_VISUAL_STATIC_GRAY) | |
| 190 { | |
| 191 /* #### Implement me!!! */ | |
| 192 return NULL; | |
| 193 } | |
| 194 | |
| 195 if (vis->type == GDK_VISUAL_PSEUDO_COLOR) | |
| 196 { | |
| 197 /* Quantize the image and get a histogram while we're at it. | |
| 198 Do this first to save memory */ | |
| 199 qtable = build_EImage_quantable(pic, width, height, 256); | |
| 200 if (qtable == NULL) return NULL; | |
| 201 } | |
| 202 | |
| 203 /* The first parameter (GdkWindow *) is allowed to be NULL if we | |
| 204 ** specify the depth */ | |
| 205 outimg = gdk_image_new (GDK_IMAGE_FASTEST, vis, width, height); | |
| 206 | |
| 207 if (!outimg) return NULL; | |
| 208 | |
| 209 byte_cnt = outimg->bpp; | |
| 210 | |
| 211 data = (unsigned char *) outimg->mem; | |
| 212 | |
| 213 if (!data) | |
| 214 { | |
| 215 gdk_image_destroy (outimg); | |
| 216 return NULL; | |
| 217 } | |
| 4252 | 218 |
| 462 | 219 if (vis->type == GDK_VISUAL_PSEUDO_COLOR) |
| 220 { | |
| 221 unsigned long pixarray[256]; | |
| 222 int pixcount, n; | |
| 223 /* use our quantize table to allocate the colors */ | |
| 224 pixcount = 32; | |
| 225 *pixtbl = xnew_array (unsigned long, pixcount); | |
| 226 *npixels = 0; | |
| 227 | |
| 228 /* ### should implement a sort by popularity to assure proper allocation */ | |
| 229 n = *npixels; | |
| 230 for (i = 0; i < qtable->num_active_colors; i++) | |
| 231 { | |
| 232 GdkColor color; | |
| 233 int res; | |
| 4252 | 234 |
| 462 | 235 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0; |
| 236 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0; | |
| 237 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0; | |
| 238 res = allocate_nearest_color (cmap, vis, &color); | |
| 239 if (res > 0 && res < 3) | |
| 240 { | |
| 241 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long); | |
| 242 (*pixtbl)[n] = color.pixel; | |
| 243 n++; | |
| 244 } | |
| 245 pixarray[i] = color.pixel; | |
| 246 } | |
| 247 *npixels = n; | |
| 248 ip = pic; | |
| 249 for (i = 0; i < height; i++) | |
| 250 { | |
| 251 dp = data + (i * outimg->bpl); | |
| 252 for (j = 0; j < width; j++) | |
| 253 { | |
| 254 rd = *ip++; | |
| 255 gr = *ip++; | |
| 256 bl = *ip++; | |
| 257 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)]; | |
| 258 #if WORDS_BIGENDIAN | |
| 259 if (outimg->byte_order == GDK_MSB_FIRST) | |
| 260 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q]; | |
| 261 else | |
| 262 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q]; | |
| 263 #else | |
| 264 if (outimg->byte_order == GDK_MSB_FIRST) | |
| 265 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q]; | |
| 266 else | |
| 267 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q]; | |
| 268 #endif | |
| 269 } | |
| 270 } | |
| 1726 | 271 xfree(qtable, quant_table *); |
| 462 | 272 } else { |
| 273 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk; | |
| 274 junk = vis->red_mask; | |
| 275 rshift = 0; | |
| 276 while ((junk & 0x1) == 0) | |
| 277 { | |
| 278 junk = junk >> 1; | |
| 279 rshift ++; | |
| 280 } | |
| 281 rbits = 0; | |
| 282 while (junk != 0) | |
| 283 { | |
| 284 junk = junk >> 1; | |
| 285 rbits++; | |
| 286 } | |
| 287 junk = vis->green_mask; | |
| 288 gshift = 0; | |
| 289 while ((junk & 0x1) == 0) | |
| 290 { | |
| 291 junk = junk >> 1; | |
| 292 gshift ++; | |
| 293 } | |
| 294 gbits = 0; | |
| 295 while (junk != 0) | |
| 296 { | |
| 297 junk = junk >> 1; | |
| 298 gbits++; | |
| 299 } | |
| 300 junk = vis->blue_mask; | |
| 301 bshift = 0; | |
| 302 while ((junk & 0x1) == 0) | |
| 303 { | |
| 304 junk = junk >> 1; | |
| 305 bshift ++; | |
| 306 } | |
| 307 bbits = 0; | |
| 308 while (junk != 0) | |
| 309 { | |
| 310 junk = junk >> 1; | |
| 311 bbits++; | |
| 312 } | |
| 313 ip = pic; | |
| 314 for (i = 0; i < height; i++) | |
| 315 { | |
| 316 dp = data + (i * outimg->bpl); | |
| 317 for (j = 0; j < width; j++) | |
| 318 { | |
| 319 if (rbits > 8) | |
| 320 rd = *ip++ << (rbits - 8); | |
| 321 else | |
| 322 rd = *ip++ >> (8 - rbits); | |
| 323 if (gbits > 8) | |
| 324 gr = *ip++ << (gbits - 8); | |
| 325 else | |
| 326 gr = *ip++ >> (8 - gbits); | |
| 327 if (bbits > 8) | |
| 328 bl = *ip++ << (bbits - 8); | |
| 329 else | |
| 330 bl = *ip++ >> (8 - bbits); | |
| 331 | |
| 332 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift); | |
| 333 #if WORDS_BIGENDIAN | |
| 334 if (outimg->byte_order == GDK_MSB_FIRST) | |
| 335 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q]; | |
| 336 else | |
| 337 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q]; | |
| 338 #else | |
| 339 if (outimg->byte_order == GDK_MSB_FIRST) | |
| 340 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q]; | |
| 341 else | |
| 342 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q]; | |
| 343 #endif | |
| 344 } | |
| 345 } | |
| 4252 | 346 } |
| 462 | 347 return outimg; |
| 348 } | |
| 349 | |
| 350 static void | |
| 351 gtk_print_image_instance (struct Lisp_Image_Instance *p, | |
| 352 Lisp_Object printcharfun, | |
| 2286 | 353 int UNUSED (escapeflag)) |
| 462 | 354 { |
| 355 switch (IMAGE_INSTANCE_TYPE (p)) | |
| 356 { | |
| 357 case IMAGE_MONO_PIXMAP: | |
| 358 case IMAGE_COLOR_PIXMAP: | |
| 359 case IMAGE_POINTER: | |
| 800 | 360 write_fmt_string (printcharfun, " (0x%lx", |
| 361 (unsigned long) IMAGE_INSTANCE_GTK_PIXMAP (p)); | |
| 462 | 362 if (IMAGE_INSTANCE_GTK_MASK (p)) |
| 800 | 363 write_fmt_string (printcharfun, "/0x%lx", |
| 364 (unsigned long) IMAGE_INSTANCE_GTK_MASK (p)); | |
| 826 | 365 write_c_string (printcharfun, ")"); |
| 462 | 366 break; |
| 2054 | 367 #ifdef HAVE_SUBWINDOWS |
| 462 | 368 case IMAGE_SUBWINDOW: |
| 369 /* #### implement me */ | |
| 370 #endif | |
| 371 default: | |
| 372 break; | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 static void | |
| 377 gtk_finalize_image_instance (struct Lisp_Image_Instance *p) | |
| 378 { | |
| 379 if (!p->data) | |
| 380 return; | |
| 381 | |
| 382 if (DEVICE_LIVE_P (XDEVICE (p->device))) | |
| 383 { | |
| 384 if (0) | |
| 385 ; | |
| 386 #ifdef HAVE_WIDGETS | |
| 387 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) | |
| 388 { | |
| 389 if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) | |
| 390 { | |
| 2054 | 391 gtk_widget_destroy ((GtkWidget*) IMAGE_INSTANCE_SUBWINDOW_ID (p)); |
| 462 | 392 |
| 393 /* We can release the callbacks again. */ | |
| 394 /* #### FIXME! */ | |
| 395 /* ungcpro_popup_callbacks (...); */ | |
| 396 | |
| 397 /* IMAGE_INSTANCE_GTK_WIDGET_ID (p) = 0; */ | |
| 398 IMAGE_INSTANCE_GTK_CLIPWIDGET (p) = 0; | |
| 399 } | |
| 400 } | |
| 401 #endif | |
| 402 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
| 403 { | |
| 2500 | 404 ABORT(); |
| 462 | 405 } |
| 406 else | |
| 407 { | |
| 408 int i; | |
| 409 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)) | |
| 410 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)); | |
| 411 | |
| 412 if (IMAGE_INSTANCE_GTK_MASK (p) && | |
| 413 IMAGE_INSTANCE_GTK_MASK (p) != IMAGE_INSTANCE_GTK_PIXMAP (p)) | |
| 414 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_MASK (p)); | |
| 415 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; | |
| 416 | |
| 417 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p)) | |
| 418 { | |
| 419 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) | |
| 420 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i)) | |
| 421 { | |
| 422 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i)); | |
| 423 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p, i) = 0; | |
| 424 } | |
| 1726 | 425 xfree (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p), GdkPixmap **); |
| 462 | 426 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p) = 0; |
| 427 } | |
| 428 | |
| 429 if (IMAGE_INSTANCE_GTK_CURSOR (p)) | |
| 430 { | |
| 431 gdk_cursor_destroy (IMAGE_INSTANCE_GTK_CURSOR (p)); | |
| 432 IMAGE_INSTANCE_GTK_CURSOR (p) = 0; | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 #if 0 | |
| 437 /* #### BILL!!! */ | |
| 438 if (IMAGE_INSTANCE_GTK_NPIXELS (p) != 0) | |
| 439 { | |
| 440 XFreeColors (dpy, | |
| 441 IMAGE_INSTANCE_GTK_COLORMAP (p), | |
| 442 IMAGE_INSTANCE_GTK_PIXELS (p), | |
| 443 IMAGE_INSTANCE_GTK_NPIXELS (p), 0); | |
| 444 IMAGE_INSTANCE_GTK_NPIXELS (p) = 0; | |
| 445 } | |
| 446 #endif | |
| 447 } | |
| 448 | |
| 449 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET | |
| 450 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW | |
| 451 && IMAGE_INSTANCE_GTK_PIXELS (p)) | |
| 452 { | |
| 1726 | 453 xfree (IMAGE_INSTANCE_GTK_PIXELS (p), unsigned long *); |
| 462 | 454 IMAGE_INSTANCE_GTK_PIXELS (p) = 0; |
| 455 } | |
| 456 | |
| 1726 | 457 xfree (p->data, void *); |
| 462 | 458 p->data = 0; |
| 459 } | |
| 460 | |
| 461 static int | |
| 462 gtk_image_instance_equal (struct Lisp_Image_Instance *p1, | |
| 2286 | 463 struct Lisp_Image_Instance *p2, int UNUSED (depth)) |
| 462 | 464 { |
| 465 switch (IMAGE_INSTANCE_TYPE (p1)) | |
| 466 { | |
| 467 case IMAGE_MONO_PIXMAP: | |
| 468 case IMAGE_COLOR_PIXMAP: | |
| 469 case IMAGE_POINTER: | |
| 470 if (IMAGE_INSTANCE_GTK_COLORMAP (p1) != IMAGE_INSTANCE_GTK_COLORMAP (p2) || | |
| 471 IMAGE_INSTANCE_GTK_NPIXELS (p1) != IMAGE_INSTANCE_GTK_NPIXELS (p2)) | |
| 472 return 0; | |
| 2054 | 473 #ifdef HAVE_SUBWINDOWS |
| 462 | 474 case IMAGE_SUBWINDOW: |
| 475 /* #### implement me */ | |
| 476 #endif | |
| 477 break; | |
| 478 default: | |
| 479 break; | |
| 480 } | |
| 481 | |
| 482 return 1; | |
| 483 } | |
| 484 | |
| 2515 | 485 static Hashcode |
| 2286 | 486 gtk_image_instance_hash (struct Lisp_Image_Instance *p, int UNUSED (depth)) |
| 462 | 487 { |
| 488 switch (IMAGE_INSTANCE_TYPE (p)) | |
| 489 { | |
| 490 case IMAGE_MONO_PIXMAP: | |
| 491 case IMAGE_COLOR_PIXMAP: | |
| 492 case IMAGE_POINTER: | |
| 493 return IMAGE_INSTANCE_GTK_NPIXELS (p); | |
| 2054 | 494 #ifdef HAVE_SUBWINDOWS |
| 462 | 495 case IMAGE_SUBWINDOW: |
| 496 /* #### implement me */ | |
| 497 return 0; | |
| 498 #endif | |
| 499 default: | |
| 500 return 0; | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 /* Set all the slots in an image instance structure to reasonable | |
| 505 default values. This is used somewhere within an instantiate | |
| 506 method. It is assumed that the device slot within the image | |
| 507 instance is already set -- this is the case when instantiate | |
| 508 methods are called. */ | |
| 509 | |
| 510 static void | |
| 511 gtk_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii, | |
| 512 int slices, | |
| 513 enum image_instance_type type) | |
| 514 { | |
| 515 ii->data = xnew_and_zero (struct gtk_image_instance_data); | |
| 516 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; | |
| 517 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (ii) = | |
| 518 xnew_array_and_zero (GdkPixmap *, slices); | |
| 519 IMAGE_INSTANCE_TYPE (ii) = type; | |
| 520 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; | |
| 521 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil; | |
| 522 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil; | |
| 523 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil; | |
| 524 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil; | |
| 525 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil; | |
| 526 } | |
| 527 | |
| 528 | |
| 529 /************************************************************************/ | |
| 530 /* pixmap file functions */ | |
| 531 /************************************************************************/ | |
| 532 | |
| 533 /* Where bitmaps are; initialized from resource database */ | |
| 534 Lisp_Object Vgtk_bitmap_file_path; | |
| 535 | |
| 536 #ifndef BITMAPDIR | |
| 537 #define BITMAPDIR "/usr/include/X11/bitmaps" | |
| 538 #endif | |
| 539 | |
| 540 /* Given a pixmap filename, look through all of the "standard" places | |
| 541 where the file might be located. Return a full pathname if found; | |
| 542 otherwise, return Qnil. */ | |
| 543 | |
| 544 static Lisp_Object | |
| 545 gtk_locate_pixmap_file (Lisp_Object name) | |
| 546 { | |
| 547 /* This function can GC if IN_REDISPLAY is false */ | |
| 548 | |
| 549 /* Check non-absolute pathnames with a directory component relative to | |
| 550 the search path; that's the way Xt does it. */ | |
| 551 /* #### Unix-specific */ | |
| 826 | 552 if (string_byte (name, 0) == '/' || |
| 553 (string_byte (name, 0) == '.' && | |
| 554 (string_byte (name, 1) == '/' || | |
| 555 (string_byte (name, 1) == '.' && | |
| 556 (string_byte (name, 2) == '/'))))) | |
| 462 | 557 { |
| 558 if (!NILP (Ffile_readable_p (name))) | |
| 559 return name; | |
| 560 else | |
| 561 return Qnil; | |
| 562 } | |
| 563 | |
| 564 if (NILP (Vgtk_bitmap_file_path)) | |
| 565 { | |
| 566 Vgtk_bitmap_file_path = nconc2 (Vgtk_bitmap_file_path, | |
| 778 | 567 (split_external_path (BITMAPDIR))); |
| 462 | 568 } |
| 569 | |
| 570 { | |
| 571 Lisp_Object found; | |
| 572 if (locate_file (Vgtk_bitmap_file_path, name, Qnil, &found, R_OK) < 0) | |
| 573 { | |
| 574 Lisp_Object temp = list1 (Vdata_directory); | |
| 575 struct gcpro gcpro1; | |
| 576 | |
| 577 GCPRO1 (temp); | |
| 578 locate_file (temp, name, Qnil, &found, R_OK); | |
| 579 UNGCPRO; | |
| 580 } | |
| 581 | |
| 582 return found; | |
| 583 } | |
| 584 } | |
| 585 | |
| 586 static Lisp_Object | |
| 587 locate_pixmap_file (Lisp_Object name) | |
| 588 { | |
| 589 return gtk_locate_pixmap_file (name); | |
| 590 } | |
| 591 | |
| 592 | |
| 593 /************************************************************************/ | |
| 594 /* cursor functions */ | |
| 595 /************************************************************************/ | |
| 596 | |
| 597 /* Check that this server supports cursors of size WIDTH * HEIGHT. If | |
| 598 not, signal an error. INSTANTIATOR is only used in the error | |
| 599 message. */ | |
| 600 | |
| 601 static void | |
| 2286 | 602 check_pointer_sizes (unsigned int UNUSED (width), unsigned int UNUSED (height), |
| 603 Lisp_Object UNUSED (instantiator)) | |
| 462 | 604 { |
| 605 /* #### BILL!!! There is no way to call XQueryBestCursor from Gdk! */ | |
| 606 #if 0 | |
| 607 unsigned int best_width, best_height; | |
| 608 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs), | |
| 609 width, height, &best_width, &best_height)) | |
| 610 /* this means that an X error of some sort occurred (we trap | |
| 611 these so they're not fatal). */ | |
| 563 | 612 gui_error ("XQueryBestCursor() failed?", instantiator); |
| 462 | 613 |
| 614 if (width > best_width || height > best_height) | |
| 563 | 615 signal_ferror_with_frob (Qgui_error, instantiator, |
| 616 "pointer too large (%dx%d): " | |
| 617 "server requires %dx%d or smaller", | |
| 618 width, height, best_width, best_height); | |
| 462 | 619 #endif |
| 620 } | |
| 621 | |
| 622 static void | |
| 623 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground, | |
| 624 Lisp_Object *background, GdkColor *xfg, GdkColor *xbg) | |
| 625 { | |
| 626 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground)) | |
| 627 *foreground = | |
| 628 Fmake_color_instance (*foreground, device, | |
| 629 encode_error_behavior_flag (ERROR_ME)); | |
| 630 if (COLOR_INSTANCEP (*foreground)) | |
| 631 *xfg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (*foreground)); | |
| 632 else | |
| 633 { | |
| 634 xfg->pixel = 0; | |
| 635 xfg->red = xfg->green = xfg->blue = 0; | |
| 636 } | |
| 637 | |
| 638 if (!NILP (*background) && !COLOR_INSTANCEP (*background)) | |
| 639 *background = | |
| 640 Fmake_color_instance (*background, device, | |
| 641 encode_error_behavior_flag (ERROR_ME)); | |
| 642 if (COLOR_INSTANCEP (*background)) | |
| 643 *xbg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (*background)); | |
| 644 else | |
| 645 { | |
| 646 xbg->pixel = 0; | |
| 647 xbg->red = xbg->green = xbg->blue = ~0; | |
| 648 } | |
| 649 } | |
| 650 | |
| 651 static void | |
| 2286 | 652 maybe_recolor_cursor (Lisp_Object UNUSED (image_instance), |
| 653 Lisp_Object UNUSED (foreground), | |
| 654 Lisp_Object UNUSED (background)) | |
| 462 | 655 { |
| 656 #if 0 | |
| 657 /* #### BILL!!! */ | |
| 658 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance); | |
| 659 GdkColor xfg, xbg; | |
| 660 | |
| 661 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg); | |
| 662 if (!NILP (foreground) || !NILP (background)) | |
| 663 { | |
| 664 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)), | |
| 665 XIMAGE_INSTANCE_GTK_CURSOR (image_instance), | |
| 666 &xfg, &xbg); | |
| 667 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground; | |
| 668 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background; | |
| 669 } | |
| 670 #else | |
| 671 /* stderr_out ("Don't know how to recolor cursors in Gtk!\n"); */ | |
| 672 #endif | |
| 673 } | |
| 674 | |
| 675 | |
| 676 /************************************************************************/ | |
| 677 /* color pixmap functions */ | |
| 678 /************************************************************************/ | |
| 679 | |
| 2959 | 680 /* Create a pointer from a color pixmap. */ |
| 681 | |
| 682 static void | |
| 683 image_instance_convert_to_pointer (Lisp_Image_Instance *ii, | |
| 684 Lisp_Object instantiator, | |
| 685 Lisp_Object pointer_fg, | |
| 686 Lisp_Object pointer_bg) | |
| 687 { | |
| 688 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 3087 | 689 GdkPixmap *pixmap = IMAGE_INSTANCE_GTK_PIXMAP (ii); |
| 690 GdkPixmap *mask = (GdkPixmap *) IMAGE_INSTANCE_GTK_MASK (ii); | |
| 2959 | 691 GdkColor fg, bg; |
| 692 int xhot = 0, yhot = 0; | |
| 693 int w, h; | |
| 694 | |
| 695 if (INTP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii))) | |
| 696 xhot = XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)); | |
| 697 if (INTP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii))) | |
| 698 yhot = XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)); | |
| 699 w = IMAGE_INSTANCE_PIXMAP_WIDTH (ii); | |
| 700 h = IMAGE_INSTANCE_PIXMAP_HEIGHT (ii); | |
| 701 | |
| 702 check_pointer_sizes (w, h, instantiator); | |
| 703 | |
| 704 /* If the loaded pixmap has colors allocated (meaning it came from an | |
| 705 XPM file), then use those as the default colors for the cursor we | |
| 706 create. Otherwise, default to pointer_fg and pointer_bg. | |
| 707 */ | |
| 708 if (DEVICE_GTK_DEPTH (XDEVICE (device)) > 1) | |
| 709 { | |
| 710 warn_when_safe (Qunimplemented, Qnotice, | |
| 711 "GTK does not support XPM cursors...\n"); | |
| 712 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new (GDK_COFFEE_MUG); | |
| 713 } | |
| 714 else | |
| 715 { | |
| 716 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg, | |
| 717 &fg, &bg); | |
| 718 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg; | |
| 719 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg; | |
| 720 IMAGE_INSTANCE_GTK_CURSOR (ii) = | |
| 721 gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, xhot, yhot); | |
| 722 } | |
| 723 } | |
| 724 | |
| 462 | 725 /* Initialize an image instance from an XImage. |
| 726 | |
| 727 DEST_MASK specifies the mask of allowed image types. | |
| 728 | |
| 729 PIXELS and NPIXELS specify an array of pixels that are used in | |
| 730 the image. These need to be kept around for the duration of the | |
| 731 image. When the image instance is freed, XFreeColors() will | |
| 732 automatically be called on all the pixels specified here; thus, | |
| 733 you should have allocated the pixels yourself using XAllocColor() | |
| 734 or the like. The array passed in is used directly without | |
| 735 being copied, so it should be heap data created with xmalloc(). | |
| 736 It will be freed using xfree() when the image instance is | |
| 737 destroyed. | |
| 738 | |
| 739 If this fails, signal an error. INSTANTIATOR is only used | |
| 740 in the error message. | |
| 741 | |
| 742 #### This should be able to handle conversion into `pointer'. | |
| 743 Use the same code as for `xpm'. */ | |
| 744 | |
| 745 static void | |
| 746 init_image_instance_from_gdk_image (struct Lisp_Image_Instance *ii, | |
| 747 GdkImage *gdk_image, | |
| 748 int dest_mask, | |
| 749 GdkColormap *cmap, | |
| 750 unsigned long *pixels, | |
| 751 int npixels, | |
| 752 int slices, | |
| 2959 | 753 Lisp_Object instantiator, |
| 754 Lisp_Object pointer_fg, | |
| 755 Lisp_Object pointer_bg) | |
| 462 | 756 { |
| 757 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 758 GdkGC *gc; | |
| 759 GdkWindow *d; | |
| 760 GdkPixmap *pixmap; | |
| 2959 | 761 enum image_instance_type type; |
| 462 | 762 |
| 763 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 764 gui_error ("Not a Gtk device", device); |
| 462 | 765 |
| 766 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | |
| 767 | |
| 2959 | 768 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) |
| 769 type = IMAGE_COLOR_PIXMAP; | |
| 770 else if (dest_mask & IMAGE_POINTER_MASK) | |
| 771 type = IMAGE_POINTER; | |
| 772 else | |
| 462 | 773 incompatible_image_types (instantiator, dest_mask, |
| 2959 | 774 IMAGE_COLOR_PIXMAP_MASK |
| 775 | IMAGE_POINTER_MASK); | |
| 462 | 776 |
| 777 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth); | |
| 778 if (!pixmap) | |
| 563 | 779 gui_error ("Unable to create pixmap", instantiator); |
| 462 | 780 |
| 781 gc = gdk_gc_new (pixmap); | |
| 782 if (!gc) | |
| 783 { | |
| 784 gdk_pixmap_unref (pixmap); | |
| 563 | 785 gui_error ("Unable to create GC", instantiator); |
| 462 | 786 } |
| 787 | |
| 788 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image, | |
| 789 0, 0, 0, 0, gdk_image->width, gdk_image->height); | |
| 790 | |
| 791 gdk_gc_destroy (gc); | |
| 792 | |
| 793 gtk_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP); | |
| 794 | |
| 795 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
| 796 find_keyword_in_vector (instantiator, Q_file); | |
| 797 | |
| 798 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; | |
|
4433
1bf48c59700e
Fix old use of rvalue on lhs to placate gcc >4.0.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4252
diff
changeset
|
799 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0; |
| 462 | 800 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = gdk_image->width; |
| 801 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = gdk_image->height; | |
| 802 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = gdk_image->depth; | |
| 803 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; | |
| 804 IMAGE_INSTANCE_GTK_PIXELS (ii) = pixels; | |
| 805 IMAGE_INSTANCE_GTK_NPIXELS (ii) = npixels; | |
| 2959 | 806 |
| 807 if (type == IMAGE_POINTER) | |
| 808 image_instance_convert_to_pointer (ii, instantiator, pointer_fg, | |
| 809 pointer_bg); | |
| 462 | 810 } |
| 811 | |
| 812 #if 0 | |
| 813 void init_image_instance_from_gdk_pixmap (struct Lisp_Image_Instance *ii, | |
| 814 struct device *device, | |
| 815 GdkPixmap *gdk_pixmap, | |
| 816 int dest_mask, | |
| 817 Lisp_Object instantiator) | |
| 818 { | |
| 819 GdkWindow *d; | |
| 820 gint width, height, depth; | |
| 821 | |
| 822 if (!DEVICE_GTK_P (device)) | |
| 2500 | 823 ABORT (); |
| 462 | 824 |
| 825 IMAGE_INSTANCE_DEVICE (ii) = device; | |
| 826 IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP; | |
| 827 | |
| 828 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (device)); | |
| 829 | |
| 830 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK)) | |
| 831 incompatible_image_types (instantiator, dest_mask, | |
| 832 IMAGE_COLOR_PIXMAP_MASK); | |
| 833 | |
| 834 gtk_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP); | |
| 835 | |
| 836 gdk_window_get_geometry (gdk_pixmap, NULL, NULL, &width, &height, &depth); | |
| 837 | |
| 838 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; | |
| 839 IMAGE_INSTANCE_GTK_PIXMAP (ii) = gdk_pixmap; | |
| 840 IMAGE_INSTANCE_GTK_MASK (ii) = 0; | |
| 841 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; | |
| 842 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; | |
| 843 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth; | |
| 844 IMAGE_INSTANCE_GTK_COLORMAP (ii) = gdk_window_get_colormap (gdk_pixmap); | |
| 845 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; | |
| 846 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; | |
| 847 } | |
| 848 #endif | |
| 849 | |
| 850 static void | |
| 851 image_instance_add_gdk_image (Lisp_Image_Instance *ii, | |
| 852 GdkImage *gdk_image, | |
| 853 int slice, | |
| 854 Lisp_Object instantiator) | |
| 855 { | |
| 856 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 857 GdkWindow *d; | |
| 858 GdkPixmap *pixmap; | |
| 859 GdkGC *gc; | |
| 860 | |
| 861 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | |
| 862 | |
| 863 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth); | |
| 864 | |
| 865 if (!pixmap) | |
| 563 | 866 gui_error ("Unable to create pixmap", instantiator); |
| 462 | 867 |
| 868 gc = gdk_gc_new (pixmap); | |
| 869 | |
| 870 if (!gc) | |
| 871 { | |
| 872 gdk_pixmap_unref (pixmap); | |
| 563 | 873 gui_error ("Unable to create GC", instantiator); |
| 462 | 874 } |
| 875 | |
| 876 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image, 0, 0, 0, 0, | |
| 877 gdk_image->width, gdk_image->height); | |
| 878 | |
| 879 gdk_gc_destroy (gc); | |
| 880 | |
| 881 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (ii, slice) = pixmap; | |
| 882 } | |
| 883 | |
| 884 static void | |
| 885 gtk_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, | |
| 886 int width, int height, | |
| 887 int slices, | |
| 4252 | 888 unsigned char *eimage, |
| 462 | 889 int dest_mask, |
| 890 Lisp_Object instantiator, | |
| 2959 | 891 Lisp_Object pointer_fg, |
| 892 Lisp_Object pointer_bg, | |
| 2286 | 893 Lisp_Object UNUSED (domain)) |
| 462 | 894 { |
| 895 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 896 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device)); | |
| 897 unsigned long *pixtbl = NULL; | |
| 898 int npixels = 0; | |
| 899 int slice; | |
| 900 GdkImage* gdk_image; | |
| 901 | |
| 902 | |
| 903 for (slice = 0; slice < slices; slice++) | |
| 904 { | |
| 905 gdk_image = convert_EImage_to_GDKImage (device, width, height, eimage, | |
| 906 &pixtbl, &npixels); | |
| 907 if (!gdk_image) | |
| 908 { | |
| 1726 | 909 if (pixtbl) |
| 910 xfree (pixtbl, unsigned long *); | |
| 462 | 911 signal_image_error("EImage to GdkImage conversion failed", instantiator); |
| 912 } | |
| 913 | |
| 914 if (slice == 0) | |
| 915 /* Now create the pixmap and set up the image instance */ | |
| 916 init_image_instance_from_gdk_image (ii, gdk_image, dest_mask, | |
| 917 cmap, pixtbl, npixels, slices, | |
| 2959 | 918 instantiator, pointer_fg, |
| 919 pointer_bg); | |
| 462 | 920 else |
| 921 image_instance_add_gdk_image (ii, gdk_image, slice, instantiator); | |
| 922 | |
| 923 if (gdk_image) | |
| 924 { | |
| 925 gdk_image_destroy (gdk_image); | |
| 926 } | |
| 927 gdk_image = 0; | |
| 928 } | |
| 929 } | |
| 930 | |
| 931 /* Given inline data for a mono pixmap, create and return the | |
| 932 corresponding X object. */ | |
| 933 | |
| 934 static GdkPixmap * | |
| 935 pixmap_from_xbm_inline (Lisp_Object device, int width, int height, | |
| 936 /* Note that data is in ext-format! */ | |
| 771 | 937 const Extbyte *bits) |
| 462 | 938 { |
| 939 return (gdk_bitmap_create_from_data (GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))), | |
| 940 (char *) bits, width, height)); | |
| 941 } | |
| 942 | |
| 943 /* Given inline data for a mono pixmap, initialize the given | |
| 944 image instance accordingly. */ | |
| 945 | |
| 946 static void | |
| 947 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii, | |
| 948 int width, int height, | |
| 949 /* Note that data is in ext-format! */ | |
| 771 | 950 const char *bits, |
| 462 | 951 Lisp_Object instantiator, |
| 952 Lisp_Object pointer_fg, | |
| 953 Lisp_Object pointer_bg, | |
| 954 int dest_mask, | |
| 955 GdkPixmap *mask, | |
| 2286 | 956 Lisp_Object UNUSED (mask_filename)) |
| 462 | 957 { |
| 958 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 959 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
| 960 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background); | |
| 961 GdkColor fg; | |
| 962 GdkColor bg; | |
| 963 enum image_instance_type type; | |
| 964 GdkWindow *draw = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); | |
| 965 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device)); | |
| 966 GdkColor black; | |
| 967 GdkColor white; | |
| 968 | |
| 969 gdk_color_black(cmap, &black); | |
| 970 gdk_color_white(cmap, &white); | |
| 971 | |
| 972 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 973 gui_error ("Not a Gtk device", device); |
| 462 | 974 |
| 975 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) && | |
| 976 (dest_mask & IMAGE_COLOR_PIXMAP_MASK)) | |
| 977 { | |
| 978 if (!NILP (foreground) || !NILP (background)) | |
| 979 type = IMAGE_COLOR_PIXMAP; | |
| 980 else | |
| 981 type = IMAGE_MONO_PIXMAP; | |
| 982 } | |
| 983 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) | |
| 984 type = IMAGE_MONO_PIXMAP; | |
| 985 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
| 986 type = IMAGE_COLOR_PIXMAP; | |
| 987 else if (dest_mask & IMAGE_POINTER_MASK) | |
| 988 type = IMAGE_POINTER; | |
| 989 else | |
| 990 incompatible_image_types (instantiator, dest_mask, | |
| 991 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | |
| 992 | IMAGE_POINTER_MASK); | |
| 993 | |
| 994 gtk_initialize_pixmap_image_instance (ii, 1, type); | |
| 995 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; | |
| 996 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; | |
| 997 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
| 998 find_keyword_in_vector (instantiator, Q_file); | |
| 999 | |
| 1000 switch (type) | |
| 1001 { | |
| 1002 case IMAGE_MONO_PIXMAP: | |
| 1003 { | |
| 1004 IMAGE_INSTANCE_GTK_PIXMAP (ii) = | |
| 1005 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits); | |
| 1006 } | |
| 1007 break; | |
| 1008 | |
| 1009 case IMAGE_COLOR_PIXMAP: | |
| 1010 { | |
| 1011 gint d = DEVICE_GTK_DEPTH (XDEVICE(device)); | |
| 1012 | |
| 1013 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground)) | |
| 1014 foreground = | |
| 1015 Fmake_color_instance (foreground, device, | |
| 1016 encode_error_behavior_flag (ERROR_ME)); | |
| 1017 | |
| 1018 if (COLOR_INSTANCEP (foreground)) | |
| 1019 fg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground)); | |
| 1020 | |
| 1021 if (!NILP (background) && !COLOR_INSTANCEP (background)) | |
| 1022 background = | |
| 1023 Fmake_color_instance (background, device, | |
| 1024 encode_error_behavior_flag (ERROR_ME)); | |
| 1025 | |
| 1026 if (COLOR_INSTANCEP (background)) | |
| 1027 bg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background)); | |
| 1028 | |
| 1029 /* We used to duplicate the pixels using XAllocColor(), to protect | |
| 1030 against their getting freed. Just as easy to just store the | |
| 1031 color instances here and GC-protect them, so this doesn't | |
| 1032 happen. */ | |
| 1033 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; | |
| 1034 IMAGE_INSTANCE_PIXMAP_BG (ii) = background; | |
| 1035 IMAGE_INSTANCE_GTK_PIXMAP (ii) = | |
| 1036 gdk_pixmap_create_from_data (draw, (char *) bits, width, height, d, &fg, &bg); | |
| 1037 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d; | |
| 1038 } | |
| 1039 break; | |
| 1040 | |
| 1041 case IMAGE_POINTER: | |
| 1042 { | |
| 1043 GdkColor fg_color, bg_color; | |
| 1044 GdkPixmap *source; | |
| 1045 | |
| 1046 check_pointer_sizes (width, height, instantiator); | |
| 1047 | |
| 1048 source = gdk_pixmap_create_from_data (draw, (char *) bits, width, height, 1, &black, &white); | |
| 1049 | |
| 1050 if (NILP (foreground)) | |
| 1051 foreground = pointer_fg; | |
| 1052 if (NILP (background)) | |
| 1053 background = pointer_bg; | |
| 1054 generate_cursor_fg_bg (device, &foreground, &background, | |
| 1055 &fg_color, &bg_color); | |
| 1056 | |
| 1057 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; | |
| 1058 IMAGE_INSTANCE_PIXMAP_BG (ii) = background; | |
| 1059 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = | |
| 1060 find_keyword_in_vector (instantiator, Q_hotspot_x); | |
| 1061 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = | |
| 1062 find_keyword_in_vector (instantiator, Q_hotspot_y); | |
| 1063 IMAGE_INSTANCE_GTK_CURSOR (ii) = | |
| 1064 gdk_cursor_new_from_pixmap (source, mask, &fg_color, &bg_color, | |
| 1065 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ? | |
| 1066 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0, | |
| 1067 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ? | |
| 1068 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0); | |
| 1069 } | |
| 1070 break; | |
| 1071 | |
| 1072 default: | |
| 2500 | 1073 ABORT (); |
| 462 | 1074 } |
| 1075 } | |
| 1076 | |
| 1077 static void | |
| 1078 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 1079 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 1080 int dest_mask, int width, int height, | |
| 1081 /* Note that data is in ext-format! */ | |
| 771 | 1082 const char *bits) |
| 462 | 1083 { |
| 1084 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data); | |
| 1085 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file); | |
| 1086 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1087 GdkPixmap *mask = 0; | |
| 2054 | 1088 const Extbyte *gcc_may_you_rot_in_hell; |
| 462 | 1089 |
| 1090 if (!NILP (mask_data)) | |
| 1091 { | |
| 1092 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))), | |
| 1093 C_STRING_ALLOCA, gcc_may_you_rot_in_hell, | |
| 1094 Qfile_name); | |
| 1095 mask = | |
| 1096 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii), | |
| 1097 XINT (XCAR (mask_data)), | |
| 1098 XINT (XCAR (XCDR (mask_data))), | |
| 1099 gcc_may_you_rot_in_hell); | |
| 1100 } | |
| 1101 | |
| 1102 init_image_instance_from_xbm_inline (ii, width, height, bits, | |
| 1103 instantiator, pointer_fg, pointer_bg, | |
| 1104 dest_mask, mask, mask_file); | |
| 1105 } | |
| 1106 | |
| 1107 /* Instantiate method for XBM's. */ | |
| 1108 | |
| 1109 static void | |
| 1110 gtk_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 1111 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 2286 | 1112 int dest_mask, Lisp_Object UNUSED (domain)) |
| 462 | 1113 { |
| 1114 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
| 771 | 1115 const char *gcc_go_home; |
| 462 | 1116 |
| 1117 assert (!NILP (data)); | |
| 1118 | |
| 1119 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))), | |
| 1120 C_STRING_ALLOCA, gcc_go_home, | |
| 1121 Qbinary); | |
| 1122 | |
| 1123 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, | |
| 1124 pointer_bg, dest_mask, XINT (XCAR (data)), | |
| 1125 XINT (XCAR (XCDR (data))), gcc_go_home); | |
| 1126 } | |
| 1127 | |
| 1128 | |
| 1129 #ifdef HAVE_XPM | |
| 1130 /********************************************************************** | |
| 1131 * XPM * | |
| 1132 **********************************************************************/ | |
| 1133 | |
| 739 | 1134 struct color_symbol |
| 1135 { | |
| 2054 | 1136 Ibyte* name; |
| 739 | 1137 GdkColor color; |
| 1138 }; | |
| 1139 | |
| 1140 static struct color_symbol* | |
| 1141 extract_xpm_color_names (Lisp_Object device, | |
| 1142 Lisp_Object domain, | |
| 1143 Lisp_Object color_symbol_alist, | |
| 1144 int* nsymbols) | |
| 1145 { | |
| 1146 /* This function can GC */ | |
| 1147 Lisp_Object rest; | |
| 1148 Lisp_Object results = Qnil; | |
| 1149 int i, j; | |
| 1150 struct color_symbol *colortbl; | |
| 1151 struct gcpro gcpro1, gcpro2; | |
| 1152 | |
| 1153 GCPRO2 (results, device); | |
| 1154 | |
| 1155 /* We built up results to be (("name" . #<color>) ...) so that if an | |
| 1156 error happens we don't lose any malloc()ed data, or more importantly, | |
| 1157 leave any pixels allocated in the server. */ | |
| 1158 i = 0; | |
| 1159 LIST_LOOP (rest, color_symbol_alist) | |
| 1160 { | |
| 1161 Lisp_Object cons = XCAR (rest); | |
| 1162 Lisp_Object name = XCAR (cons); | |
| 1163 Lisp_Object value = XCDR (cons); | |
| 1164 if (NILP (value)) | |
| 1165 continue; | |
| 1166 if (STRINGP (value)) | |
| 1167 value = | |
| 1168 Fmake_color_instance | |
| 793 | 1169 (value, device, encode_error_behavior_flag (ERROR_ME_DEBUG_WARN)); |
| 739 | 1170 else |
| 4252 | 1171 { |
| 1172 assert (COLOR_SPECIFIERP (value)); | |
| 1173 value = Fspecifier_instance (value, domain, Qnil, Qnil); | |
| 1174 } | |
| 739 | 1175 |
| 1176 if (NILP (value)) | |
| 4252 | 1177 continue; |
| 739 | 1178 results = noseeum_cons (noseeum_cons (name, value), results); |
| 1179 i++; | |
| 1180 } | |
| 1181 UNGCPRO; /* no more evaluation */ | |
| 1182 | |
| 1183 *nsymbols=i; | |
| 1184 if (i == 0) return 0; | |
| 1185 | |
| 1186 colortbl = xnew_array_and_zero (struct color_symbol, i); | |
| 1187 | |
| 1188 for (j=0; j<i; j++) | |
| 1189 { | |
| 1190 Lisp_Object cons = XCAR (results); | |
| 4252 | 1191 colortbl[j].color = |
| 739 | 1192 * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (XCDR (cons))); |
| 1193 | |
| 2054 | 1194 colortbl[j].name = XSTRING_DATA (XCAR (cons)); |
| 1195 free_cons (cons); | |
| 739 | 1196 cons = results; |
| 1197 results = XCDR (results); | |
| 2054 | 1198 free_cons (cons); |
| 739 | 1199 } |
| 1200 return colortbl; | |
| 1201 } | |
| 1202 | |
| 462 | 1203 static void |
| 739 | 1204 gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, |
| 462 | 1205 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
| 1206 int dest_mask, Lisp_Object domain) | |
| 1207 { | |
| 1208 /* This function can GC */ | |
| 1209 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1210 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 1211 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
| 1212 GdkColormap *cmap; | |
| 1213 int depth; | |
| 1214 GdkVisual *visual; | |
| 1215 GdkPixmap *pixmap; | |
| 1216 GdkPixmap *mask = 0; | |
| 1217 GdkWindow *window = 0; | |
| 739 | 1218 int nsymbols = 0, i = 0; |
| 1219 struct color_symbol *color_symbols = NULL; | |
| 462 | 1220 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, |
| 1221 Q_color_symbols); | |
| 1222 enum image_instance_type type; | |
| 1223 int force_mono; | |
| 2054 | 1224 gint w, h; |
| 2082 | 1225 struct gcpro gcpro1, gcpro2, gcpro3; |
| 2367 | 1226 const Binbyte * volatile dstring; |
| 462 | 1227 |
| 1228 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 1229 gui_error ("Not a Gtk device", device); |
| 462 | 1230 |
| 1231 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
| 1232 type = IMAGE_COLOR_PIXMAP; | |
| 1233 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) | |
| 1234 type = IMAGE_MONO_PIXMAP; | |
| 1235 else if (dest_mask & IMAGE_POINTER_MASK) | |
| 1236 type = IMAGE_POINTER; | |
| 1237 else | |
| 1238 incompatible_image_types (instantiator, dest_mask, | |
| 1239 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | |
| 1240 | IMAGE_POINTER_MASK); | |
| 1241 force_mono = (type != IMAGE_COLOR_PIXMAP); | |
| 1242 | |
| 2082 | 1243 GCPRO3 (device, data, color_symbol_alist); |
| 771 | 1244 |
| 462 | 1245 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))); |
| 1246 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device)); | |
| 1247 depth = DEVICE_GTK_DEPTH (XDEVICE (device)); | |
| 1248 visual = DEVICE_GTK_VISUAL (XDEVICE (device)); | |
| 1249 | |
| 1250 gtk_initialize_pixmap_image_instance (ii, 1, type); | |
| 1251 | |
| 1252 assert (!NILP (data)); | |
| 1253 | |
| 2082 | 1254 /* Extract all the entries from xpm-color-symbols */ |
| 771 | 1255 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, |
| 1256 &nsymbols); | |
| 2082 | 1257 assert (!NILP (data)); |
| 1258 | |
| 1259 LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary); | |
| 1260 | |
| 1261 /* | |
| 1262 * GTK only uses the 'c' color entry of an XPM and doesn't use the symbolic | |
| 1263 * color names at all. This is unfortunate because the way to change the | |
| 1264 * colors from lisp is by adding the symbolic names, and the new colors, to | |
| 1265 * the variable xpm-color-symbols. | |
| 1266 * | |
| 1267 * To get around this decode the XPM, add a 'c' entry of the desired color | |
| 1268 * for each matching symbolic color, recode the XPM and pass it to GTK. The | |
| 1269 * decode and recode stages aren't too bad because this also performs the | |
| 1270 * external to internal format translation, which avoids contortions like | |
| 1271 * writing the XPM back to disk in order to get it processed. | |
| 1272 */ | |
| 771 | 1273 { |
| 2082 | 1274 XpmImage image; |
| 1275 XpmInfo info; | |
| 1276 char** data; | |
| 1277 | |
| 1278 XpmCreateXpmImageFromBuffer ((char*) dstring, &image, &info); | |
| 1279 | |
| 1280 for (i = 0; i < nsymbols; i++) | |
| 1281 { | |
| 1282 unsigned j; | |
| 1283 | |
| 1284 for (j = 0; j < image.ncolors; j++) | |
| 1285 { | |
| 1286 if (image.colorTable[j].symbolic != NULL && | |
| 2367 | 1287 !qxestrcasecmp_ascii(color_symbols[i].name, image.colorTable[j].symbolic)) |
| 2082 | 1288 { |
| 2367 | 1289 image.colorTable[j].c_color = xnew_ascbytes (16); |
| 2082 | 1290 |
| 1291 sprintf(image.colorTable[j].c_color, "#%.4x%.4x%.4x", | |
| 1292 color_symbols[i].color.red, color_symbols[i].color.green, | |
| 1293 color_symbols[i].color.blue); | |
| 1294 } | |
| 1295 } | |
| 1296 } | |
| 1297 | |
| 1298 XpmCreateDataFromXpmImage (&data, &image, &info); | |
| 1299 | |
| 1300 pixmap = gdk_pixmap_create_from_xpm_d (window, &mask, NULL, | |
| 1301 data); | |
| 771 | 1302 } |
| 462 | 1303 |
| 1726 | 1304 if (color_symbols) |
| 1305 xfree (color_symbols, struct color_symbol *); | |
| 739 | 1306 |
| 462 | 1307 if (!pixmap) |
| 1308 signal_image_error ("Error reading pixmap", data); | |
| 1309 | |
| 1310 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth); | |
| 1311 | |
| 1312 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; | |
| 3087 | 1313 IMAGE_INSTANCE_PIXMAP_MASK (ii) = mask; |
| 462 | 1314 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; |
| 1315 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; | |
| 1316 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; | |
| 1317 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w; | |
| 1318 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h; | |
| 1319 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
| 1320 find_keyword_in_vector (instantiator, Q_file); | |
| 1321 | |
| 1322 switch (type) | |
| 1323 { | |
| 1324 case IMAGE_MONO_PIXMAP: | |
| 1325 break; | |
| 1326 | |
| 1327 case IMAGE_COLOR_PIXMAP: | |
| 771 | 1328 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth; |
| 462 | 1329 break; |
| 1330 | |
| 1331 case IMAGE_POINTER: | |
| 3087 | 1332 /* #### Gtk does not give us access to the hotspots of a pixmap */ |
| 1333 | |
| 1334 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = 1; | |
| 1335 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = 1; | |
| 1336 | |
| 4252 | 1337 |
| 2959 | 1338 image_instance_convert_to_pointer (ii, instantiator, pointer_fg, |
| 1339 pointer_bg); | |
| 462 | 1340 break; |
| 1341 | |
| 1342 default: | |
| 2500 | 1343 ABORT (); |
| 462 | 1344 } |
| 771 | 1345 |
| 1346 UNGCPRO; | |
| 462 | 1347 } |
| 1348 #endif /* HAVE_XPM */ | |
| 1349 | |
| 1350 | |
| 1351 #ifdef HAVE_XFACE | |
| 1352 | |
| 1353 /********************************************************************** | |
| 1354 * X-Face * | |
| 1355 **********************************************************************/ | |
| 1356 #if defined(EXTERN) | |
| 1357 /* This is about to get redefined! */ | |
| 1358 #undef EXTERN | |
| 1359 #endif | |
| 1360 /* We have to define SYSV32 so that compface.h includes string.h | |
| 1361 instead of strings.h. */ | |
| 1362 #define SYSV32 | |
| 1743 | 1363 BEGIN_C_DECLS |
| 462 | 1364 #include <compface.h> |
| 1743 | 1365 END_C_DECLS |
| 1366 | |
| 462 | 1367 /* JMP_BUF cannot be used here because if it doesn't get defined |
| 1368 to jmp_buf we end up with a conflicting type error with the | |
| 1369 definition in compface.h */ | |
| 1370 extern jmp_buf comp_env; | |
| 1371 #undef SYSV32 | |
| 1372 | |
| 1373 static void | |
| 1374 gtk_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 2286 | 1375 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
| 1376 int dest_mask, Lisp_Object UNUSED (domain)) | |
| 462 | 1377 { |
| 1378 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
| 1379 int i, stattis; | |
| 1380 char *p, *bits, *bp; | |
| 771 | 1381 const char * volatile emsg = 0; |
| 1382 const char * volatile dstring; | |
| 462 | 1383 |
| 1384 assert (!NILP (data)); | |
| 1385 | |
| 1386 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary); | |
| 1387 | |
| 1388 if ((p = strchr (dstring, ':'))) | |
| 1389 { | |
| 1390 dstring = p + 1; | |
| 1391 } | |
| 1392 | |
| 1393 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */ | |
| 1394 if (!(stattis = setjmp (comp_env))) | |
| 1395 { | |
| 1396 UnCompAll ((char *) dstring); | |
| 1397 UnGenFace (); | |
| 1398 } | |
| 1399 | |
| 1400 switch (stattis) | |
| 1401 { | |
| 1402 case -2: | |
| 1403 emsg = "uncompface: internal error"; | |
| 1404 break; | |
| 1405 case -1: | |
| 1406 emsg = "uncompface: insufficient or invalid data"; | |
| 1407 break; | |
| 1408 case 1: | |
| 1409 emsg = "uncompface: excess data ignored"; | |
| 1410 break; | |
| 1411 } | |
| 1412 | |
| 1413 if (emsg) | |
| 563 | 1414 gui_error_2 (emsg, data, Qimage); |
| 462 | 1415 |
| 851 | 1416 bp = bits = (char *) ALLOCA (PIXELS / 8); |
| 462 | 1417 |
| 1418 /* the compface library exports char F[], which uses a single byte per | |
| 1419 pixel to represent a 48x48 bitmap. Yuck. */ | |
| 1420 for (i = 0, p = F; i < (PIXELS / 8); ++i) | |
| 1421 { | |
| 1422 int n, b; | |
| 1423 /* reverse the bit order of each byte... */ | |
| 1424 for (b = n = 0; b < 8; ++b) | |
| 1425 { | |
| 1426 n |= ((*p++) << b); | |
| 1427 } | |
| 1428 *bp++ = (char) n; | |
| 1429 } | |
| 1430 | |
| 1431 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, | |
| 1432 pointer_bg, dest_mask, 48, 48, bits); | |
| 1433 } | |
| 1434 | |
| 1435 #endif /* HAVE_XFACE */ | |
| 1436 | |
| 1437 /********************************************************************** | |
| 1438 * RESOURCES * | |
| 1439 **********************************************************************/ | |
| 1440 | |
| 1441 static void | |
| 1442 gtk_resource_validate (Lisp_Object instantiator) | |
| 1443 { | |
| 4252 | 1444 if ((NILP (find_keyword_in_vector (instantiator, Q_file)) |
| 462 | 1445 && |
| 4252 | 1446 NILP (find_keyword_in_vector (instantiator, Q_resource_id))) |
| 462 | 1447 || |
| 1448 NILP (find_keyword_in_vector (instantiator, Q_resource_type))) | |
| 563 | 1449 sferror ("Must supply :file, :resource-id and :resource-type", |
| 462 | 1450 instantiator); |
| 1451 } | |
| 1452 | |
| 1453 static Lisp_Object | |
| 563 | 1454 gtk_resource_normalize (Lisp_Object inst, Lisp_Object console_type, |
| 1455 Lisp_Object dest_mask) | |
| 462 | 1456 { |
| 563 | 1457 return shared_resource_normalize (inst, console_type, dest_mask, |
| 1458 Qgtk_resource); | |
| 462 | 1459 } |
| 1460 | |
| 1461 static int | |
| 1462 gtk_resource_possible_dest_types (void) | |
| 1463 { | |
| 1464 return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK; | |
| 1465 } | |
| 1466 | |
| 1467 extern guint symbol_to_enum (Lisp_Object, GtkType); | |
| 1468 | |
| 2272 | 1469 static guint resource_name_to_resource (Lisp_Object name, |
| 1470 enum image_instance_type type) | |
| 462 | 1471 { |
| 1472 if (type == IMAGE_POINTER) | |
| 1473 return (symbol_to_enum (name, GTK_TYPE_GDK_CURSOR_TYPE)); | |
| 1474 else | |
| 1475 return (0); | |
| 1476 } | |
| 1477 | |
| 2272 | 1478 static enum image_instance_type |
| 462 | 1479 resource_symbol_to_type (Lisp_Object data) |
| 1480 { | |
| 1481 if (EQ (data, Qcursor)) | |
| 1482 return IMAGE_POINTER; | |
| 1483 #if 0 | |
| 1484 else if (EQ (data, Qicon)) | |
| 1485 return IMAGE_ICON; | |
| 1486 else if (EQ (data, Qbitmap)) | |
| 1487 return IMAGE_BITMAP; | |
| 1488 #endif | |
| 1489 else | |
| 2054 | 1490 return IMAGE_UNKNOWN; |
| 462 | 1491 } |
| 1492 | |
| 1493 static void | |
| 1494 gtk_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 2286 | 1495 Lisp_Object UNUSED (pointer_fg), |
| 1496 Lisp_Object UNUSED (pointer_bg), | |
| 1497 int UNUSED (dest_mask), Lisp_Object UNUSED (domain)) | |
| 462 | 1498 { |
| 1499 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1500 GdkCursor *c = NULL; | |
| 2272 | 1501 enum image_instance_type type; |
| 462 | 1502 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
| 1503 Lisp_Object resource_type = find_keyword_in_vector (instantiator, Q_resource_type); | |
| 1504 Lisp_Object resource_id = find_keyword_in_vector (instantiator, Q_resource_id); | |
| 1505 | |
| 1506 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 1507 gui_error ("Not a GTK device", device); |
| 462 | 1508 |
| 1509 type = resource_symbol_to_type (resource_type); | |
| 1510 | |
| 595 | 1511 #if 0 |
| 1512 if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_POINTER_MASK) | |
| 1513 iitype = IMAGE_POINTER; | |
| 1514 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
| 1515 iitype = IMAGE_COLOR_PIXMAP; | |
| 4252 | 1516 else |
| 595 | 1517 incompatible_image_types (instantiator, dest_mask, |
| 4252 | 1518 IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); |
| 595 | 1519 #endif |
| 4252 | 1520 |
| 462 | 1521 /* mess with the keyword info we were provided with */ |
| 1522 gtk_initialize_pixmap_image_instance (ii, 1, type); | |
| 2054 | 1523 c = gdk_cursor_new ((GdkCursorType) resource_name_to_resource (resource_id, type)); |
| 462 | 1524 IMAGE_INSTANCE_GTK_CURSOR (ii) = c; |
| 1525 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = resource_id; | |
| 1526 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 10; | |
| 1527 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 10; | |
| 1528 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1; | |
| 1529 } | |
| 1530 | |
| 1531 static void | |
| 1532 check_valid_resource_symbol (Lisp_Object data) | |
| 1533 { | |
| 1534 CHECK_SYMBOL (data); | |
| 1535 if (!resource_symbol_to_type (data)) | |
| 563 | 1536 invalid_constant ("invalid resource type", data); |
| 462 | 1537 } |
| 1538 | |
| 1539 static void | |
| 1540 check_valid_resource_id (Lisp_Object data) | |
| 1541 { | |
| 1542 if (!resource_name_to_resource (data, IMAGE_POINTER) | |
| 1543 && | |
| 1544 !resource_name_to_resource (data, IMAGE_COLOR_PIXMAP) | |
| 1545 #if 0 | |
| 1546 && | |
| 1547 !resource_name_to_resource (data, IMAGE_BITMAP) | |
| 1548 #endif | |
| 1549 ) | |
| 563 | 1550 invalid_constant ("invalid resource identifier", data); |
| 462 | 1551 } |
| 1552 | |
| 1553 #if 0 | |
| 1554 void | |
| 1555 check_valid_string_or_int (Lisp_Object data) | |
| 1556 { | |
| 1557 if (!INTP (data)) | |
| 1558 CHECK_STRING (data); | |
| 1559 else | |
| 1560 CHECK_INT (data); | |
| 1561 } | |
| 1562 #endif | |
| 1563 | |
| 1564 | |
| 1565 /********************************************************************** | |
| 1566 * Autodetect * | |
| 1567 **********************************************************************/ | |
| 1568 | |
| 1569 static void | |
| 1570 autodetect_validate (Lisp_Object instantiator) | |
| 1571 { | |
| 1572 data_must_be_present (instantiator); | |
| 1573 } | |
| 1574 | |
| 1575 static Lisp_Object | |
| 1576 autodetect_normalize (Lisp_Object instantiator, | |
| 1577 Lisp_Object console_type, | |
| 2286 | 1578 Lisp_Object UNUSED (dest_mask)) |
| 462 | 1579 { |
| 1580 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data); | |
| 1581 Lisp_Object filename = Qnil; | |
| 1582 Lisp_Object data = Qnil; | |
| 1583 struct gcpro gcpro1, gcpro2, gcpro3; | |
| 1584 Lisp_Object alist = Qnil; | |
| 1585 | |
| 1586 GCPRO3 (filename, data, alist); | |
| 1587 | |
| 1588 if (NILP (file)) /* no conversion necessary */ | |
| 1589 RETURN_UNGCPRO (instantiator); | |
| 1590 | |
| 1591 alist = tagged_vector_to_alist (instantiator); | |
| 1592 | |
| 1593 filename = locate_pixmap_file (file); | |
| 1594 if (!NILP (filename)) | |
| 1595 { | |
| 1596 int xhot, yhot; | |
| 1597 /* #### Apparently some versions of XpmReadFileToData, which is | |
| 1598 called by pixmap_to_lisp_data, don't return an error value | |
| 1599 if the given file is not a valid XPM file. Instead, they | |
| 1600 just seg fault. It is definitely caused by passing a | |
| 1601 bitmap. To try and avoid this we check for bitmaps first. */ | |
| 1602 | |
| 1603 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1); | |
| 1604 | |
| 1605 if (!EQ (data, Qt)) | |
| 1606 { | |
| 1607 alist = remassq_no_quit (Q_data, alist); | |
| 1608 alist = Fcons (Fcons (Q_file, filename), | |
| 1609 Fcons (Fcons (Q_data, data), alist)); | |
| 1610 if (xhot != -1) | |
| 1611 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)), | |
| 1612 alist); | |
| 1613 if (yhot != -1) | |
| 1614 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)), | |
| 1615 alist); | |
| 1616 | |
| 4252 | 1617 alist = xbm_mask_file_munging (alist, filename, Qt, console_type); |
| 462 | 1618 |
| 1619 { | |
| 1620 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist); | |
| 1621 free_alist (alist); | |
| 1622 RETURN_UNGCPRO (result); | |
| 1623 } | |
| 1624 } | |
| 1625 | |
| 1626 #ifdef HAVE_XPM | |
| 1627 data = pixmap_to_lisp_data (filename, 1); | |
| 1628 | |
| 1629 if (!EQ (data, Qt)) | |
| 1630 { | |
| 1631 alist = remassq_no_quit (Q_data, alist); | |
| 1632 alist = Fcons (Fcons (Q_file, filename), | |
| 1633 Fcons (Fcons (Q_data, data), alist)); | |
| 1634 alist = Fcons (Fcons (Q_color_symbols, | |
| 1635 evaluate_xpm_color_symbols ()), | |
| 1636 alist); | |
| 1637 { | |
| 1638 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist); | |
| 1639 free_alist (alist); | |
| 1640 RETURN_UNGCPRO (result); | |
| 1641 } | |
| 1642 } | |
| 1643 #endif | |
| 1644 } | |
| 1645 | |
| 1646 /* If we couldn't convert it, just put it back as it is. | |
| 1647 We might try to further frob it later as a cursor-font | |
| 1648 specification. (We can't do that now because we don't know | |
| 1649 what dest-types it's going to be instantiated into.) */ | |
| 1650 { | |
| 1651 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist); | |
| 1652 free_alist (alist); | |
| 1653 RETURN_UNGCPRO (result); | |
| 1654 } | |
| 1655 } | |
| 1656 | |
| 1657 static int | |
| 1658 autodetect_possible_dest_types (void) | |
| 1659 { | |
| 1660 return | |
| 1661 IMAGE_MONO_PIXMAP_MASK | | |
| 1662 IMAGE_COLOR_PIXMAP_MASK | | |
| 1663 IMAGE_POINTER_MASK | | |
| 1664 IMAGE_TEXT_MASK; | |
| 1665 } | |
| 1666 | |
| 1667 static void | |
| 1668 autodetect_instantiate (Lisp_Object image_instance, | |
| 1669 Lisp_Object instantiator, | |
| 1670 Lisp_Object pointer_fg, | |
| 1671 Lisp_Object pointer_bg, | |
| 1672 int dest_mask, Lisp_Object domain) | |
| 1673 { | |
| 1674 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
| 1675 struct gcpro gcpro1, gcpro2, gcpro3; | |
| 1676 Lisp_Object alist = Qnil; | |
| 1677 Lisp_Object result = Qnil; | |
| 1678 int is_cursor_font = 0; | |
| 1679 | |
| 1680 GCPRO3 (data, alist, result); | |
| 1681 | |
| 1682 alist = tagged_vector_to_alist (instantiator); | |
| 1683 if (dest_mask & IMAGE_POINTER_MASK) | |
| 1684 { | |
| 771 | 1685 const char *name_ext; |
| 462 | 1686 |
| 1687 TO_EXTERNAL_FORMAT (LISP_STRING, data, | |
| 1688 C_STRING_ALLOCA, name_ext, | |
| 1689 Qfile_name); | |
| 1690 | |
| 1691 if (cursor_name_to_index (name_ext) != -1) | |
| 4252 | 1692 { |
| 1693 result = alist_to_tagged_vector (Qcursor_font, alist); | |
| 1694 is_cursor_font = 1; | |
| 1695 } | |
| 462 | 1696 } |
| 1697 | |
| 1698 if (!is_cursor_font) | |
| 1699 result = alist_to_tagged_vector (Qstring, alist); | |
| 1700 free_alist (alist); | |
| 1701 | |
| 1702 if (is_cursor_font) | |
| 1703 cursor_font_instantiate (image_instance, result, pointer_fg, | |
| 1704 pointer_bg, dest_mask, domain); | |
| 1705 else | |
| 1706 string_instantiate (image_instance, result, pointer_fg, | |
| 1707 pointer_bg, dest_mask, domain); | |
| 1708 | |
| 1709 UNGCPRO; | |
| 1710 } | |
| 1711 | |
| 1712 | |
| 1713 /********************************************************************** | |
| 1714 * Font * | |
| 1715 **********************************************************************/ | |
| 1716 | |
| 1717 static void | |
| 1718 font_validate (Lisp_Object instantiator) | |
| 1719 { | |
| 1720 data_must_be_present (instantiator); | |
| 1721 } | |
| 1722 | |
| 1723 static int | |
| 1724 font_possible_dest_types (void) | |
| 1725 { | |
| 1726 return IMAGE_POINTER_MASK; | |
| 1727 } | |
| 1728 | |
| 1729 static void | |
| 1730 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 1731 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 2286 | 1732 int dest_mask, Lisp_Object UNUSED (domain)) |
| 462 | 1733 { |
| 1734 /* This function can GC */ | |
| 1735 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
| 1736 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1737 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 1738 GdkColor fg, bg; | |
| 1739 GdkFont *source, *mask; | |
| 2421 | 1740 char source_name[PATH_MAX_INTERNAL], mask_name[PATH_MAX_INTERNAL], dummy; |
| 462 | 1741 int source_char, mask_char; |
| 1742 int count; | |
| 1743 Lisp_Object foreground, background; | |
| 1744 | |
| 1745 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 1746 gui_error ("Not a Gtk device", device); |
| 462 | 1747 |
| 1748 if (!STRINGP (data) || | |
| 1749 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5)) | |
| 563 | 1750 invalid_argument ("Invalid font-glyph instantiator", |
| 462 | 1751 instantiator); |
| 1752 | |
| 1753 if (!(dest_mask & IMAGE_POINTER_MASK)) | |
| 1754 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK); | |
| 1755 | |
| 1756 foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
| 1757 if (NILP (foreground)) | |
| 1758 foreground = pointer_fg; | |
| 1759 background = find_keyword_in_vector (instantiator, Q_background); | |
| 1760 if (NILP (background)) | |
| 1761 background = pointer_bg; | |
| 1762 | |
| 1763 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg); | |
| 1764 | |
| 1765 count = sscanf ((char *) XSTRING_DATA (data), | |
| 1766 "FONT %s %d %s %d %c", | |
| 1767 source_name, &source_char, | |
| 1768 mask_name, &mask_char, &dummy); | |
| 1769 /* Allow "%s %d %d" as well... */ | |
| 1770 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy))) | |
| 1771 count = 4, mask_name[0] = 0; | |
| 1772 | |
| 1773 if (count != 2 && count != 4) | |
| 563 | 1774 syntax_error ("invalid cursor specification", data); |
| 462 | 1775 source = gdk_font_load (source_name); |
| 1776 if (! source) | |
| 563 | 1777 gui_error_2 ("couldn't load font", |
| 462 | 1778 build_string (source_name), |
| 1779 data); | |
| 1780 if (count == 2) | |
| 1781 mask = 0; | |
| 1782 else if (!mask_name[0]) | |
| 1783 mask = source; | |
| 1784 else | |
| 1785 { | |
| 1786 mask = gdk_font_load (mask_name); | |
| 1787 if (!mask) | |
| 1788 /* continuable */ | |
| 771 | 1789 Fsignal (Qgui_error, list3 (build_msg_string ("couldn't load font"), |
| 563 | 1790 build_string (mask_name), data)); |
| 462 | 1791 } |
| 1792 if (!mask) | |
| 1793 mask_char = 0; | |
| 1794 | |
| 1795 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */ | |
| 1796 | |
| 1797 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); | |
| 1798 | |
| 1799 IMAGE_INSTANCE_GTK_CURSOR (ii) = NULL; | |
| 1800 | |
| 1801 #if 0 | |
| 1802 /* #### BILL!!! There is no way to call this function from Gdk */ | |
| 1803 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char, | |
| 1804 &fg, &bg); | |
| 1805 #endif | |
| 1806 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground; | |
| 1807 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background; | |
| 1808 | |
| 1809 gdk_font_unref (source); | |
| 1810 if (mask && mask != source) gdk_font_unref (mask); | |
| 1811 } | |
| 1812 | |
| 1813 | |
| 1814 /********************************************************************** | |
| 1815 * Cursor-Font * | |
| 1816 **********************************************************************/ | |
| 1817 | |
| 1818 static void | |
| 1819 cursor_font_validate (Lisp_Object instantiator) | |
| 1820 { | |
| 1821 data_must_be_present (instantiator); | |
| 1822 } | |
| 1823 | |
| 1824 static int | |
| 1825 cursor_font_possible_dest_types (void) | |
| 1826 { | |
| 1827 return IMAGE_POINTER_MASK; | |
| 1828 } | |
| 1829 | |
| 1830 static char *__downcase (const char *name) | |
| 1831 { | |
| 1832 char *converted = strdup(name); | |
| 1833 char *work = converted; | |
| 1834 | |
| 1835 while (*work) | |
| 1836 { | |
| 1837 *work = tolower(*work); | |
| 1838 work++; | |
| 1839 } | |
| 1840 return(converted); | |
| 1841 } | |
| 1842 | |
| 1843 /* This is basically the equivalent of XmuCursorNameToIndex */ | |
| 2054 | 1844 static GdkCursorType |
| 462 | 1845 cursor_name_to_index (const char *name) |
| 1846 { | |
| 1847 int i; | |
| 1848 static char *the_gdk_cursors[GDK_NUM_GLYPHS]; | |
| 1849 | |
| 1850 if (!the_gdk_cursors[GDK_BASED_ARROW_UP]) | |
| 1851 { | |
| 1852 /* Need to initialize the array */ | |
| 1853 /* Supposedly since this array is static it should be | |
| 4252 | 1854 initialized to NULLs for us, but I'm very paranoid. */ |
| 462 | 1855 for (i = 0; i < GDK_NUM_GLYPHS; i++) |
| 1856 { | |
| 1857 the_gdk_cursors[i] = NULL; | |
| 1858 } | |
| 1859 | |
| 1860 #define FROB_CURSOR(x) the_gdk_cursors[GDK_##x] = __downcase(#x) | |
| 1861 FROB_CURSOR(ARROW); FROB_CURSOR(BASED_ARROW_DOWN); | |
| 1862 FROB_CURSOR(BASED_ARROW_UP); FROB_CURSOR(BOAT); | |
| 1863 FROB_CURSOR(BOGOSITY); FROB_CURSOR(BOTTOM_LEFT_CORNER); | |
| 1864 FROB_CURSOR(BOTTOM_RIGHT_CORNER); FROB_CURSOR(BOTTOM_SIDE); | |
| 1865 FROB_CURSOR(BOTTOM_TEE); FROB_CURSOR(BOX_SPIRAL); | |
| 1866 FROB_CURSOR(CENTER_PTR); FROB_CURSOR(CIRCLE); | |
| 1867 FROB_CURSOR(CLOCK); FROB_CURSOR(COFFEE_MUG); | |
| 1868 FROB_CURSOR(CROSS); FROB_CURSOR(CROSS_REVERSE); | |
| 1869 FROB_CURSOR(CROSSHAIR); FROB_CURSOR(DIAMOND_CROSS); | |
| 1870 FROB_CURSOR(DOT); FROB_CURSOR(DOTBOX); | |
| 1871 FROB_CURSOR(DOUBLE_ARROW); FROB_CURSOR(DRAFT_LARGE); | |
| 1872 FROB_CURSOR(DRAFT_SMALL); FROB_CURSOR(DRAPED_BOX); | |
| 1873 FROB_CURSOR(EXCHANGE); FROB_CURSOR(FLEUR); | |
| 1874 FROB_CURSOR(GOBBLER); FROB_CURSOR(GUMBY); | |
| 1875 FROB_CURSOR(HAND1); FROB_CURSOR(HAND2); | |
| 1876 FROB_CURSOR(HEART); FROB_CURSOR(ICON); | |
| 1877 FROB_CURSOR(IRON_CROSS); FROB_CURSOR(LEFT_PTR); | |
| 1878 FROB_CURSOR(LEFT_SIDE); FROB_CURSOR(LEFT_TEE); | |
| 1879 FROB_CURSOR(LEFTBUTTON); FROB_CURSOR(LL_ANGLE); | |
| 1880 FROB_CURSOR(LR_ANGLE); FROB_CURSOR(MAN); | |
| 1881 FROB_CURSOR(MIDDLEBUTTON); FROB_CURSOR(MOUSE); | |
| 1882 FROB_CURSOR(PENCIL); FROB_CURSOR(PIRATE); | |
| 1883 FROB_CURSOR(PLUS); FROB_CURSOR(QUESTION_ARROW); | |
| 1884 FROB_CURSOR(RIGHT_PTR); FROB_CURSOR(RIGHT_SIDE); | |
| 1885 FROB_CURSOR(RIGHT_TEE); FROB_CURSOR(RIGHTBUTTON); | |
| 1886 FROB_CURSOR(RTL_LOGO); FROB_CURSOR(SAILBOAT); | |
| 1887 FROB_CURSOR(SB_DOWN_ARROW); FROB_CURSOR(SB_H_DOUBLE_ARROW); | |
| 1888 FROB_CURSOR(SB_LEFT_ARROW); FROB_CURSOR(SB_RIGHT_ARROW); | |
| 1889 FROB_CURSOR(SB_UP_ARROW); FROB_CURSOR(SB_V_DOUBLE_ARROW); | |
| 1890 FROB_CURSOR(SHUTTLE); FROB_CURSOR(SIZING); | |
| 1891 FROB_CURSOR(SPIDER); FROB_CURSOR(SPRAYCAN); | |
| 1892 FROB_CURSOR(STAR); FROB_CURSOR(TARGET); | |
| 1893 FROB_CURSOR(TCROSS); FROB_CURSOR(TOP_LEFT_ARROW); | |
| 1894 FROB_CURSOR(TOP_LEFT_CORNER); FROB_CURSOR(TOP_RIGHT_CORNER); | |
| 1895 FROB_CURSOR(TOP_SIDE); FROB_CURSOR(TOP_TEE); | |
| 1896 FROB_CURSOR(TREK); FROB_CURSOR(UL_ANGLE); | |
| 1897 FROB_CURSOR(UMBRELLA); FROB_CURSOR(UR_ANGLE); | |
| 1898 FROB_CURSOR(WATCH); FROB_CURSOR(XTERM); | |
| 1899 FROB_CURSOR(X_CURSOR); | |
| 1900 #undef FROB_CURSOR | |
| 1901 } | |
| 1902 | |
| 1903 for (i = 0; i < GDK_NUM_GLYPHS; i++) | |
| 1904 { | |
| 1905 if (!the_gdk_cursors[i]) continue; | |
| 1906 if (!strcmp (the_gdk_cursors[i], name)) | |
| 1907 { | |
| 2054 | 1908 return (GdkCursorType) i; |
| 462 | 1909 } |
| 1910 } | |
| 2054 | 1911 return (GdkCursorType) -1; |
| 462 | 1912 } |
| 1913 | |
| 1914 static void | |
| 1915 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 1916 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 2286 | 1917 int dest_mask, Lisp_Object UNUSED (domain)) |
| 462 | 1918 { |
| 1919 /* This function can GC */ | |
| 1920 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
| 1921 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1922 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 2054 | 1923 GdkCursorType i; |
| 771 | 1924 const char *name_ext; |
| 462 | 1925 Lisp_Object foreground, background; |
| 1926 | |
| 1927 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 1928 gui_error ("Not a Gtk device", device); |
| 462 | 1929 |
| 1930 if (!(dest_mask & IMAGE_POINTER_MASK)) | |
| 1931 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK); | |
| 1932 | |
| 1933 TO_EXTERNAL_FORMAT (LISP_STRING, data, | |
| 1934 C_STRING_ALLOCA, name_ext, | |
| 1935 Qfile_name); | |
| 1936 | |
| 1937 if ((i = cursor_name_to_index (name_ext)) == -1) | |
| 563 | 1938 invalid_argument ("Unrecognized cursor-font name", data); |
| 462 | 1939 |
| 1940 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); | |
| 1941 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new (i); | |
| 1942 foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
| 1943 if (NILP (foreground)) | |
| 1944 foreground = pointer_fg; | |
| 1945 background = find_keyword_in_vector (instantiator, Q_background); | |
| 1946 if (NILP (background)) | |
| 1947 background = pointer_bg; | |
| 1948 maybe_recolor_cursor (image_instance, foreground, background); | |
| 1949 } | |
| 1950 | |
| 1951 static int | |
| 1952 gtk_colorize_image_instance (Lisp_Object image_instance, | |
| 1953 Lisp_Object foreground, Lisp_Object background); | |
| 1954 | |
| 1955 | |
| 1956 /************************************************************************/ | |
| 1957 /* subwindow and widget support */ | |
| 1958 /************************************************************************/ | |
| 1959 | |
| 1960 /* unmap the image if it is a widget. This is used by redisplay via | |
| 1961 redisplay_unmap_subwindows */ | |
| 1962 static void | |
| 1963 gtk_unmap_subwindow (Lisp_Image_Instance *p) | |
| 1964 { | |
| 1965 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
| 1966 { | |
| 1967 /* We don't support subwindows, but we do support widgets... */ | |
| 2500 | 1968 ABORT (); |
| 462 | 1969 } |
| 1970 else /* must be a widget */ | |
| 1971 { | |
| 1972 /* Since we are being unmapped we want the enclosing frame to | |
| 1973 get focus. The losing with simple scrolling but is the safest | |
| 1974 thing to do. */ | |
| 1975 if (IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) | |
| 1976 gtk_widget_unmap (IMAGE_INSTANCE_GTK_CLIPWIDGET (p)); | |
| 1977 } | |
| 1978 } | |
| 1979 | |
| 1980 /* map the subwindow. This is used by redisplay via | |
| 1981 redisplay_output_subwindow */ | |
| 1982 static void | |
| 1983 gtk_map_subwindow (Lisp_Image_Instance *p, int x, int y, | |
| 691 | 1984 struct display_glyph_area* dga) |
| 462 | 1985 { |
| 1986 assert (dga->width > 0 && dga->height > 0); | |
| 1987 | |
| 1988 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
| 1989 { | |
| 1990 /* No subwindow support... */ | |
| 2500 | 1991 ABORT (); |
| 462 | 1992 } |
| 1993 else /* must be a widget */ | |
| 1994 { | |
| 1995 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p)); | |
| 1996 GtkWidget *wid = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); | |
| 1997 GtkAllocation a; | |
| 2168 | 1998 int moving; |
| 462 | 1999 |
| 2000 if (!wid) return; | |
| 2001 | |
| 2002 a.x = x + IMAGE_INSTANCE_GTK_WIDGET_XOFFSET (p); | |
| 2003 a.y = y + IMAGE_INSTANCE_GTK_WIDGET_YOFFSET (p); | |
| 2004 a.width = dga->width; | |
| 2005 a.height = dga->height; | |
| 2006 | |
| 2168 | 2007 /* Is the widget cganging position? */ |
| 2008 moving = (a.x != wid->allocation.x) || | |
| 2009 (a.y != wid->allocation.y); | |
| 2010 | |
| 462 | 2011 if ((a.width != wid->allocation.width) || |
| 2168 | 2012 (a.height != wid->allocation.height) || |
| 2013 moving) | |
| 462 | 2014 { |
| 2015 gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a); | |
| 2016 } | |
| 2017 | |
| 2168 | 2018 if (moving) |
| 462 | 2019 { |
| 2020 guint32 old_flags = GTK_WIDGET_FLAGS (FRAME_GTK_TEXT_WIDGET (f)); | |
| 2021 | |
| 2168 | 2022 /* GtkFixed widget queues a resize when you add a widget. |
| 462 | 2023 ** But only if it is visible. |
| 2024 ** losers. | |
| 2025 */ | |
| 2026 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) &= ~GTK_VISIBLE; | |
| 2168 | 2027 |
| 462 | 2028 if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p)) |
| 2029 { | |
| 2030 gtk_fixed_move (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
| 2031 wid, | |
| 2168 | 2032 a.x, a.y); |
| 462 | 2033 } |
| 2034 else | |
| 2035 { | |
| 2036 IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE; | |
| 2037 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
| 2038 wid, | |
| 2168 | 2039 a.x, a.y); |
| 462 | 2040 } |
| 2168 | 2041 |
| 462 | 2042 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) = old_flags; |
| 2043 } | |
| 691 | 2044 else |
| 2045 { | |
| 2046 if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p)) | |
| 2047 { | |
| 2048 /* Do nothing... */ | |
| 2049 } | |
| 2050 else | |
| 2051 { | |
| 2052 /* Must make sure we have put the image at least once! */ | |
| 2053 IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE; | |
| 2054 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
| 2055 wid, | |
| 2168 | 2056 a.x, a.y); |
| 691 | 2057 } |
| 2058 } | |
| 462 | 2059 |
| 2060 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) | |
| 2061 { | |
| 2062 gtk_widget_map (wid); | |
| 2063 } | |
| 2064 | |
| 2065 gtk_widget_draw (wid, NULL); | |
| 2066 } | |
| 2067 } | |
| 2068 | |
| 2069 /* when you click on a widget you may activate another widget this | |
| 2070 needs to be checked and all appropriate widgets updated */ | |
| 2071 static void | |
| 2072 gtk_redisplay_subwindow (Lisp_Image_Instance *p) | |
| 2073 { | |
| 2074 /* Update the subwindow size if necessary. */ | |
| 2075 if (IMAGE_INSTANCE_SIZE_CHANGED (p)) | |
| 2076 { | |
| 2077 #if 0 | |
| 2078 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
| 2079 IMAGE_INSTANCE_X_SUBWINDOW_ID (p), | |
| 2080 IMAGE_INSTANCE_WIDTH (p), | |
| 2081 IMAGE_INSTANCE_HEIGHT (p)); | |
| 2082 #endif | |
| 2083 } | |
| 2084 } | |
| 2085 | |
| 2086 /* Update all attributes that have changed. */ | |
| 2087 static void | |
| 2088 gtk_redisplay_widget (Lisp_Image_Instance *p) | |
| 2089 { | |
| 2090 /* This function can GC if IN_REDISPLAY is false. */ | |
| 2091 | |
| 2092 if (!IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) | |
| 2093 return; | |
| 2094 | |
| 2095 #ifdef HAVE_WIDGETS | |
| 2096 /* First get the items if they have changed since this is a | |
| 2097 structural change. As such it will nuke all added values so we | |
| 2098 need to update most other things after the items have changed.*/ | |
| 2099 gtk_widget_show_all (IMAGE_INSTANCE_GTK_CLIPWIDGET (p)); | |
| 2100 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
| 2101 { | |
| 2102 /* Need to update GtkArgs that might have changed... */ | |
| 2103 /* #### FIXME!!! */ | |
| 2054 | 2104 /*Lisp_Object image_instance = wrap_image_instance (p); */ |
| 462 | 2105 } |
| 2106 else | |
| 2107 { | |
| 2108 /* #### FIXME!!! */ | |
| 2109 /* No items changed, so do nothing, right? */ | |
| 2110 } | |
| 2111 | |
| 2112 /* Possibly update the colors and font */ | |
| 2113 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) | |
| 2114 || | |
| 2115 /* #### This is not sufficient because it will not cope with widgets | |
| 2116 that are not currently visible. Once redisplay has done the | |
| 2117 visible ones it will clear this flag so that when new ones | |
| 2118 become visible they will not be updated. */ | |
| 2119 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed | |
| 2120 || | |
| 2121 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed | |
| 2122 || | |
| 2123 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
| 2124 { | |
| 2125 /* #### Write this function BILL! */ | |
| 2126 update_widget_face (NULL, p, IMAGE_INSTANCE_FRAME (p)); | |
| 2127 } | |
| 2128 | |
| 2129 /* Possibly update the text. */ | |
| 2130 if (IMAGE_INSTANCE_TEXT_CHANGED (p)) | |
| 2131 { | |
| 2132 char* str; | |
| 2133 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p); | |
| 2134 LISP_STRING_TO_EXTERNAL (val, str, Qnative); | |
| 2135 | |
| 2136 /* #### Need to special case each type of GtkWidget here! */ | |
| 2137 } | |
| 2138 | |
| 2139 /* Possibly update the size. */ | |
| 2140 if (IMAGE_INSTANCE_SIZE_CHANGED (p) | |
| 2141 || | |
| 2142 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p) | |
| 2143 || | |
| 2144 IMAGE_INSTANCE_TEXT_CHANGED (p)) | |
| 2145 { | |
| 2168 | 2146 GtkRequisition r; |
| 2147 GtkAllocation a = IMAGE_INSTANCE_GTK_CLIPWIDGET (p)->allocation; | |
| 2148 | |
| 462 | 2149 assert (IMAGE_INSTANCE_GTK_WIDGET_ID (p) && |
| 2150 IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) ; | |
| 2151 | |
| 2168 | 2152 a.width = r.width = IMAGE_INSTANCE_WIDTH (p); |
| 2153 a.height = r.height = IMAGE_INSTANCE_HEIGHT (p); | |
| 2154 | |
| 2155 /* Force the widget's preferred and actual size to what we say it shall | |
| 2156 be. */ | |
| 2157 gtk_widget_size_request (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &r); | |
| 2158 gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a); | |
| 462 | 2159 } |
| 2160 | |
| 2161 /* Adjust offsets within the frame. */ | |
| 2162 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed) | |
| 2163 { | |
| 2164 /* I don't think we need to do anything for Gtk here... */ | |
| 2165 } | |
| 2166 | |
| 2167 /* now modify the widget */ | |
| 2168 #endif | |
| 2169 } | |
| 2170 | |
| 2171 /* instantiate and gtk type subwindow */ | |
| 2172 static void | |
| 2286 | 2173 gtk_subwindow_instantiate (Lisp_Object image_instance, |
| 2174 Lisp_Object UNUSED (instantiator), | |
| 2175 Lisp_Object UNUSED (pointer_fg), | |
| 2176 Lisp_Object UNUSED (pointer_bg), | |
| 2177 int UNUSED (dest_mask), Lisp_Object UNUSED (domain)) | |
| 462 | 2178 { |
| 2179 /* This function can GC */ | |
| 2180 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 2181 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
| 2182 | |
| 2183 if (!DEVICE_GTK_P (XDEVICE (device))) | |
| 563 | 2184 gui_error ("Not a GTK device", device); |
| 462 | 2185 |
| 2186 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW; | |
| 2187 | |
| 2188 ii->data = xnew_and_zero (struct gtk_subwindow_data); | |
| 2189 | |
| 2190 /* Create a window for clipping */ | |
| 2191 IMAGE_INSTANCE_GTK_CLIPWINDOW (ii) = NULL; | |
| 2192 | |
| 2193 /* Now put the subwindow inside the clip window. */ | |
| 2194 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) NULL; | |
| 2195 } | |
| 2196 | |
| 2197 #ifdef HAVE_WIDGETS | |
| 2198 | |
| 2199 /************************************************************************/ | |
| 2200 /* widgets */ | |
| 2201 /************************************************************************/ | |
| 2202 static void | |
| 2203 update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii, | |
| 2204 Lisp_Object domain) | |
| 2205 { | |
| 2206 if (0) | |
| 2207 { | |
| 2208 GtkStyle *style = gtk_widget_get_style (w); | |
| 2209 Lisp_Object pixel = Qnil; | |
| 2210 GdkColor *fcolor, *bcolor; | |
| 2211 | |
| 2212 style = gtk_style_copy (style); | |
| 4252 | 2213 |
| 462 | 2214 /* Update the foreground. */ |
| 2215 pixel = FACE_FOREGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain); | |
| 2216 fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel)); | |
| 2217 | |
| 2218 /* Update the background. */ | |
| 2219 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain); | |
| 2220 bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel)); | |
| 2221 | |
| 2222 /* Update the font */ | |
| 2223 /* #### FIXME!!! Need to copy the widgets style, dick with it, and | |
| 2224 ** set the widgets style to the new style... | |
| 2225 */ | |
| 2226 gtk_widget_set_style (w, style); | |
| 2227 | |
| 2228 /* #### Megahack - but its just getting too complicated to do this | |
| 2229 in the right place. */ | |
| 2230 #if 0 | |
| 2231 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control)) | |
| 2232 update_tab_widget_face (wv, ii, domain); | |
| 2233 #endif | |
| 2234 } | |
| 2235 } | |
| 2236 | |
| 2237 #if 0 | |
| 2238 static void | |
| 2239 update_tab_widget_face (GtkWidget *w, Lisp_Image_Instance *ii, | |
| 2240 Lisp_Object domain) | |
| 2241 { | |
| 2242 if (wv->contents) | |
| 2243 { | |
| 2244 widget_value* val = wv->contents, *cur; | |
| 2245 | |
| 2246 /* Give each child label the correct foreground color. */ | |
| 2247 Lisp_Object pixel = FACE_FOREGROUND | |
| 2248 (IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 2249 domain); | |
| 2250 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); | |
| 2251 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel); | |
| 2252 wv->change = VISIBLE_CHANGE; | |
| 2253 val->change = VISIBLE_CHANGE; | |
| 2254 | |
| 2255 for (cur = val->next; cur; cur = cur->next) | |
| 2256 { | |
| 2257 cur->change = VISIBLE_CHANGE; | |
| 2258 if (cur->value) | |
| 2259 { | |
| 2260 lw_copy_widget_value_args (val, cur); | |
| 2261 } | |
| 2262 } | |
| 2263 } | |
| 2264 } | |
| 2265 #endif | |
| 2266 | |
| 2267 static Lisp_Object | |
| 2268 gtk_widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 2269 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 2270 Lisp_Object domain) | |
| 2271 { | |
| 2272 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 2273 Lisp_Object widget = Qnil; | |
| 2274 char *nm = NULL; | |
| 2275 GtkWidget *w = NULL; | |
| 2276 struct gcpro gcpro1; | |
| 2277 | |
| 2278 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; | |
| 2279 | |
| 2280 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) | |
| 2281 { | |
| 2282 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative); | |
| 2283 } | |
| 2284 | |
| 2285 ii->data = xnew_and_zero (struct gtk_subwindow_data); | |
| 2286 | |
| 2287 /* Create a clipping widget */ | |
| 2288 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = NULL; | |
| 2289 IMAGE_INSTANCE_GTK_ALREADY_PUT(ii) = FALSE; | |
| 2290 | |
| 2291 /* Create the actual widget */ | |
| 2292 GCPRO1 (widget); | |
| 2293 widget = call5 (Qgtk_widget_instantiate_internal, | |
| 2294 image_instance, instantiator, | |
| 2295 pointer_fg, pointer_bg, | |
| 2296 domain); | |
| 2297 | |
| 2298 if (!NILP (widget)) | |
| 2299 { | |
| 2300 CHECK_GTK_OBJECT (widget); | |
| 2301 w = GTK_WIDGET (XGTK_OBJECT (widget)->object); | |
| 2302 } | |
| 2303 else | |
| 2304 { | |
| 2305 stderr_out ("Lisp-level creation of widget failed... falling back\n"); | |
| 2306 w = gtk_label_new ("Widget Creation Failed..."); | |
| 2307 } | |
| 2308 | |
| 2309 UNGCPRO; | |
| 2310 | |
| 2311 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) w; | |
| 2312 | |
| 2313 /* #### HACK!!!! We should make this do the right thing if we | |
| 2314 ** really need a clip widget! | |
| 2315 */ | |
| 2316 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = w; | |
| 2317 | |
| 2168 | 2318 /* The current theme may produce a widget of a different size that what we |
| 2319 expect so force reconsideration of the widget's size. */ | |
| 2320 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1; | |
| 2321 | |
| 462 | 2322 return (Qt); |
| 2323 } | |
| 2324 | |
| 2325 static void | |
| 2326 gtk_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 2327 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 2286 | 2328 int UNUSED (dest_mask), Lisp_Object domain) |
| 462 | 2329 { |
| 2330 call_with_suspended_errors ((lisp_fn_t) gtk_widget_instantiate_1, | |
| 2331 Qnil, Qimage, | |
| 2332 ERROR_ME_WARN, 5, | |
| 2333 image_instance, instantiator, | |
| 2334 pointer_fg, | |
| 2335 pointer_bg, | |
| 2336 domain); | |
| 2337 } | |
| 2338 | |
| 2339 /* get properties of a control */ | |
| 2340 static Lisp_Object | |
| 2286 | 2341 gtk_widget_property (Lisp_Object UNUSED (image_instance), Lisp_Object prop) |
| 462 | 2342 { |
| 2343 /* Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); */ | |
| 2344 | |
| 2345 /* get the text from a control */ | |
| 2346 if (EQ (prop, Q_text)) | |
| 2347 { | |
| 2348 return Qnil; | |
| 2349 } | |
| 2350 return Qunbound; | |
| 2351 } | |
| 2352 | |
| 2353 #define FAKE_GTK_WIDGET_INSTANTIATOR(x) \ | |
| 2354 static void \ | |
| 2355 gtk_##x##_instantiate (Lisp_Object image_instance, \ | |
| 2356 Lisp_Object instantiator, \ | |
| 2357 Lisp_Object pointer_fg, \ | |
| 2358 Lisp_Object pointer_bg, \ | |
| 2359 int dest_mask, Lisp_Object domain) \ | |
| 2360 { \ | |
| 2361 gtk_widget_instantiate (image_instance, instantiator, pointer_fg, \ | |
| 2362 pointer_bg, dest_mask, domain); \ | |
| 2363 } | |
| 2364 | |
| 2365 FAKE_GTK_WIDGET_INSTANTIATOR(native_layout); | |
| 2366 FAKE_GTK_WIDGET_INSTANTIATOR(button); | |
| 2367 FAKE_GTK_WIDGET_INSTANTIATOR(progress_gauge); | |
| 2368 FAKE_GTK_WIDGET_INSTANTIATOR(edit_field); | |
| 2369 FAKE_GTK_WIDGET_INSTANTIATOR(combo_box); | |
| 2370 FAKE_GTK_WIDGET_INSTANTIATOR(label); | |
| 2168 | 2371 /* Note: tab_control has a custom instantiator (see below) */ |
| 2372 | |
| 2373 /* | |
| 2374 Ask the widget to return it's preferred size. This device method must | |
| 2375 defined for all widgets that also have format specific version of | |
| 2376 query_geometry defined in glyphs-widget.c. This is because those format | |
| 2377 specific versions return sizes that are appropriate for the X widgets. For | |
| 2378 GTK, the size of a widget can change at runtime due to the user changing | |
| 2379 their theme. | |
| 2380 | |
| 2381 This method can be called before the widget is instantiated. This is | |
| 2382 because instantiate_image_instantiator() is tying to be helpful to other | |
| 2383 toolkits and supply sane geometry values to them. This is not appropriate | |
| 2384 for GTK and can be ignored. | |
| 2385 | |
| 2386 This method can be used by all widgets. | |
| 2387 */ | |
| 2388 static void | |
| 2389 gtk_widget_query_geometry (Lisp_Object image_instance, | |
| 2390 int* width, int* height, | |
| 2286 | 2391 enum image_instance_geometry UNUSED (disp), |
| 2392 Lisp_Object UNUSED (domain)) | |
| 2168 | 2393 { |
| 2394 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); | |
| 2395 | |
| 2396 if (p->data != NULL) | |
| 2397 { | |
| 2398 GtkWidget *w = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); | |
| 2399 GtkRequisition r; | |
| 2400 | |
| 2401 gtk_widget_size_request(w, &r); | |
| 2402 *height= r.height; | |
| 2403 *width = r.width; | |
| 2404 } | |
| 2405 } | |
| 2406 | |
| 2407 | |
| 2408 /* Button functions. */ | |
| 462 | 2409 |
| 2410 /* Update a button's clicked state. */ | |
| 2411 static void | |
| 2412 gtk_button_redisplay (Lisp_Object image_instance) | |
| 2413 { | |
| 2414 /* This function can GC if IN_REDISPLAY is false. */ | |
| 2415 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); | |
| 2416 GtkWidget *w = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); | |
| 2417 | |
| 2418 if (GTK_WIDGET_TYPE (w) == gtk_button_get_type ()) | |
| 2419 { | |
| 2420 } | |
| 2421 else if (GTK_WIDGET_TYPE (w) == gtk_check_button_get_type ()) | |
| 2422 { | |
| 2423 } | |
| 2424 else if (GTK_WIDGET_TYPE (w) == gtk_radio_button_get_type ()) | |
| 2425 { | |
| 2426 } | |
| 2427 else | |
| 2428 { | |
| 2429 /* Unknown button type... */ | |
| 2500 | 2430 ABORT(); |
| 462 | 2431 } |
| 2432 } | |
| 2433 | |
| 2434 /* get properties of a button */ | |
| 2435 static Lisp_Object | |
| 2436 gtk_button_property (Lisp_Object image_instance, Lisp_Object prop) | |
| 2437 { | |
| 2438 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 2439 | |
| 2440 /* check the state of a button */ | |
| 2441 if (EQ (prop, Q_selected)) | |
| 2442 { | |
| 2443 if (GTK_WIDGET_HAS_FOCUS (IMAGE_INSTANCE_SUBWINDOW_ID (ii))) | |
| 2444 return Qt; | |
| 2445 else | |
| 2446 return Qnil; | |
| 2447 } | |
| 2448 return Qunbound; | |
| 2449 } | |
| 2450 | |
| 2168 | 2451 |
| 2452 /* Progress gauge functions. */ | |
| 2453 | |
| 462 | 2454 /* set the properties of a progress gauge */ |
| 2455 static void | |
| 2456 gtk_progress_gauge_redisplay (Lisp_Object image_instance) | |
| 2457 { | |
| 2458 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 2459 | |
| 2460 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) | |
| 2461 { | |
| 2462 gfloat f; | |
| 2463 Lisp_Object val; | |
| 2464 | |
| 2465 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value; | |
| 2466 f = XFLOATINT (val); | |
| 2467 | |
| 2468 gtk_progress_set_value (GTK_PROGRESS (IMAGE_INSTANCE_SUBWINDOW_ID (ii)), | |
| 2469 f); | |
| 2470 } | |
| 2471 } | |
| 2472 | |
| 2168 | 2473 |
| 2474 /* Tab Control functions. */ | |
| 2475 | |
| 2476 /* | |
| 2477 Register a widget's callbacks with the frame's hashtable. The hashtable is | |
| 2478 weak so deregistration is handled automatically. Tab controls have per-tab | |
| 2479 callback list functions and the GTK callback architecture is not | |
| 2480 sufficiently flexible to deal with this. Instead, the functions are | |
| 2481 registered here and the id is passed through the callback loop. | |
| 2482 */ | |
| 2483 static int | |
| 2484 gtk_register_gui_item (Lisp_Object image_instance, Lisp_Object gui, | |
| 2485 Lisp_Object domain) | |
| 2486 { | |
| 2487 struct frame *f = XFRAME(DOMAIN_FRAME(domain)); | |
| 2488 int id = gui_item_id_hash(FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE(f), | |
| 2489 gui, WIDGET_GLYPH_SLOT); | |
| 2490 | |
| 2491 Fputhash(make_int(id), image_instance, | |
| 2492 FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f)); | |
| 2493 Fputhash(make_int(id), XGUI_ITEM (gui)->callback, | |
| 2494 FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f)); | |
| 2495 Fputhash(make_int(id), XGUI_ITEM (gui)->callback_ex, | |
| 2496 FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f)); | |
| 2497 return id; | |
| 2498 } | |
| 2499 | |
| 2500 /* | |
| 2501 Append the given item as a tab to the notebook. Callbacks, etc are all | |
| 2502 setup. | |
| 2503 */ | |
| 2504 static void | |
| 2505 gtk_add_tab_item(Lisp_Object image_instance, | |
| 2506 GtkNotebook* nb, Lisp_Object item, | |
| 2286 | 2507 Lisp_Object domain, int UNUSED (i)) |
| 2168 | 2508 { |
| 2509 Lisp_Object name; | |
| 2510 int hash_id = 0; | |
| 2511 char *c_name = NULL; | |
| 2512 GtkWidget* box; | |
| 2513 | |
| 2514 if (GUI_ITEMP (item)) | |
| 2515 { | |
| 2516 Lisp_Gui_Item *pgui = XGUI_ITEM (item); | |
| 2517 | |
| 2518 if (!STRINGP (pgui->name)) | |
| 2519 pgui->name = eval_within_redisplay (pgui->name); | |
| 2520 | |
| 2521 if (!STRINGP (pgui->name)) { | |
| 2522 warn_when_safe (Qredisplay, Qwarning, | |
| 2523 "Name does not evaluate to string"); | |
| 2524 | |
| 2525 return; | |
| 2526 } | |
| 2527 | |
| 2528 hash_id = gtk_register_gui_item (image_instance, item, domain); | |
| 2529 name = pgui->name; | |
| 2530 } | |
| 2531 else | |
| 2532 { | |
| 2533 CHECK_STRING (item); | |
| 2534 name = item; | |
| 2535 } | |
| 2536 | |
| 2537 TO_EXTERNAL_FORMAT (LISP_STRING, name, | |
| 2538 C_STRING_ALLOCA, c_name, | |
| 2539 Qctext); | |
| 2540 | |
| 2541 /* Dummy widget that the notbook wants to display when a tab is selected. */ | |
| 2542 box = gtk_vbox_new (FALSE, 3); | |
| 2543 | |
| 2544 /* | |
| 2545 Store the per-tab callback data id in the tab. The callback functions | |
| 2546 themselves could have been stored in the widget but this avoids having to | |
| 2547 worry about the garbage collector running between here and the callback | |
| 2548 function. | |
| 2549 */ | |
| 2550 gtk_object_set_data(GTK_OBJECT(box), GTK_DATA_TAB_HASHCODE_IDENTIFIER, | |
| 2551 (gpointer) hash_id); | |
| 2552 | |
| 2553 gtk_notebook_append_page (nb, box, gtk_label_new (c_name)); | |
| 2554 } | |
| 2555 | |
| 2556 /* Signal handler for the switch-page signal. */ | |
| 2557 static void gtk_tab_control_callback(GtkNotebook *notebook, | |
| 2558 GtkNotebookPage *page, | |
| 2286 | 2559 gint UNUSED (page_num), |
| 2560 gpointer UNUSED (user_data)) | |
| 2168 | 2561 { |
| 2562 /* | |
| 2563 This callback is called for every selection, not just user selection. | |
| 2564 We're only interested in user selection, which occurs outside of | |
| 2565 redisplay. | |
| 2566 */ | |
| 2567 | |
| 2568 if (!in_display) | |
| 2569 { | |
| 2570 Lisp_Object image_instance, callback, callback_ex; | |
| 2571 Lisp_Object frame, event; | |
| 2572 int update_subwindows_p = 0; | |
| 2573 struct frame *f = gtk_widget_to_frame(GTK_WIDGET(notebook)); | |
| 2574 int id; | |
| 2575 | |
| 2576 if (!f) | |
| 2577 return; | |
| 2578 frame = wrap_frame (f); | |
| 2579 | |
| 2580 id = (int) gtk_object_get_data(GTK_OBJECT(page->child), | |
| 2581 GTK_DATA_TAB_HASHCODE_IDENTIFIER); | |
| 2582 image_instance = Fgethash(make_int_verify(id), | |
| 2583 FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE(f), Qnil); | |
| 2584 callback = Fgethash(make_int(id), | |
| 2585 FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE(f), Qnil); | |
| 2586 callback_ex = Fgethash(make_int(id), | |
| 2587 FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE(f), Qnil); | |
| 2588 update_subwindows_p = 1; | |
| 2589 | |
| 2590 /* It is possible for a widget action to cause it to get out of | |
| 2591 sync with its instantiator. Thus it is necessary to signal | |
| 2592 this possibility. */ | |
| 2593 if (IMAGE_INSTANCEP (image_instance)) | |
| 2594 XIMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (image_instance) = 1; | |
| 4252 | 2595 |
| 2168 | 2596 if (!NILP (callback_ex) && !UNBOUNDP (callback_ex)) |
| 2597 { | |
| 2598 event = Fmake_event (Qnil, Qnil); | |
| 2599 | |
| 2600 XSET_EVENT_TYPE (event, misc_user_event); | |
| 2601 XSET_EVENT_CHANNEL (event, frame); | |
| 2602 XSET_EVENT_MISC_USER_FUNCTION (event, Qeval); | |
| 2603 XSET_EVENT_MISC_USER_OBJECT (event, list4 (Qfuncall, callback_ex, image_instance, event)); | |
| 2604 } | |
| 2605 else if (NILP (callback) || UNBOUNDP (callback)) | |
| 2606 event = Qnil; | |
| 2607 else | |
| 2608 { | |
| 2609 Lisp_Object fn, arg; | |
| 2610 | |
| 2611 event = Fmake_event (Qnil, Qnil); | |
| 2612 | |
| 2613 get_gui_callback (callback, &fn, &arg); | |
| 2614 XSET_EVENT_TYPE (event, misc_user_event); | |
| 2615 XSET_EVENT_CHANNEL (event, frame); | |
| 2616 XSET_EVENT_MISC_USER_FUNCTION (event, fn); | |
| 2617 XSET_EVENT_MISC_USER_OBJECT (event, arg); | |
| 2618 } | |
| 2619 | |
| 2620 if (!NILP (event)) | |
| 2621 enqueue_dispatch_event (event); | |
| 2622 | |
| 2623 /* The result of this evaluation could cause other instances to change so | |
| 2624 enqueue an update callback to check this. */ | |
| 2625 if (update_subwindows_p && !NILP (event)) | |
| 2626 enqueue_magic_eval_event (update_widget_instances, frame); | |
| 2627 } | |
| 2628 } | |
| 2629 | |
| 2630 /* Create a tab_control widget. The special handling of the individual tabs | |
| 2631 means that the normal instantiation code cannot be used. */ | |
| 2632 static void | |
| 2633 gtk_tab_control_instantiate (Lisp_Object image_instance, | |
| 2634 Lisp_Object instantiator, | |
| 2635 Lisp_Object pointer_fg, | |
| 2636 Lisp_Object pointer_bg, | |
| 2637 int dest_mask, Lisp_Object domain) | |
| 2638 { | |
| 2639 Lisp_Object rest; | |
| 2640 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 2641 int i = 0; | |
| 2642 int selected = 0; | |
| 2643 GtkNotebook *nb; | |
| 2644 | |
| 2645 /* The normal instantiation is still needed. */ | |
| 2646 gtk_widget_instantiate (image_instance, instantiator, pointer_fg, | |
| 2647 pointer_bg, dest_mask, domain); | |
| 2648 | |
| 2649 nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)); | |
| 2650 | |
| 2651 /* Add items to the tab, find the current selection */ | |
| 2652 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
| 2653 { | |
| 2654 gtk_add_tab_item (image_instance, nb, XCAR (rest), domain, i); | |
| 2655 | |
| 2656 if (gui_item_selected_p (XCAR (rest))) | |
| 2657 selected = i; | |
| 2658 | |
| 2659 i++; | |
| 2660 } | |
| 2661 | |
| 2662 gtk_notebook_set_page(nb, selected); | |
| 2663 | |
| 2664 /* Call per-tab lisp callback when a tab is pressed. */ | |
| 2665 gtk_signal_connect (GTK_OBJECT (nb), "switch-page", | |
| 2666 GTK_SIGNAL_FUNC (gtk_tab_control_callback), NULL); | |
| 2667 } | |
| 2668 | |
| 462 | 2669 /* Set the properties of a tab control */ |
| 2670 static void | |
| 2671 gtk_tab_control_redisplay (Lisp_Object image_instance) | |
| 2672 { | |
| 2673 /* #### Convert this to GTK baby! */ | |
| 2674 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 2675 | |
| 2676 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) || | |
| 2677 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii)) | |
| 2678 { | |
| 2679 /* If only the order has changed then simply select the first | |
| 2680 one of the pending set. This stops horrendous rebuilding - | |
| 2681 and hence flicker - of the tabs each time you click on | |
| 2682 one. */ | |
| 2683 if (tab_control_order_only_changed (image_instance)) | |
| 2684 { | |
| 2168 | 2685 int i = 0; |
| 462 | 2686 Lisp_Object rest, selected = |
| 2687 gui_item_list_find_selected | |
| 2688 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ? | |
| 2689 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) : | |
| 2690 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))); | |
| 2691 | |
| 2692 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
| 2693 { | |
| 1913 | 2694 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0)) |
| 462 | 2695 { |
| 2696 Lisp_Object old_selected =gui_item_list_find_selected | |
| 2697 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))); | |
| 2698 | |
| 2699 /* Pick up the new selected item. */ | |
| 2700 XGUI_ITEM (old_selected)->selected = | |
| 2701 XGUI_ITEM (XCAR (rest))->selected; | |
| 2702 XGUI_ITEM (XCAR (rest))->selected = | |
| 2703 XGUI_ITEM (selected)->selected; | |
| 2704 /* We're not actually changing the items anymore. */ | |
| 2705 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; | |
| 2706 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; | |
| 2168 | 2707 |
| 2708 gtk_notebook_set_page(GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)), | |
| 2709 i); | |
| 462 | 2710 break; |
| 2711 } | |
| 2168 | 2712 |
| 2713 i++; | |
| 462 | 2714 } |
| 2715 } | |
| 2716 else | |
| 2717 { | |
| 2718 /* More than just the order has changed... let's get busy! */ | |
| 2719 GtkNotebook *nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)); | |
| 2720 guint num_pages = g_list_length (nb->children); | |
| 2721 Lisp_Object rest; | |
| 2168 | 2722 int i; |
| 2723 | |
| 2724 /* Why is there no API to remove everything from a notebook? */ | |
| 462 | 2725 if (num_pages >= 0) |
| 2726 { | |
| 2727 for (i = num_pages; i >= 0; --i) | |
| 2728 { | |
| 2729 gtk_notebook_remove_page (nb, i); | |
| 2730 } | |
| 2731 } | |
| 2732 | |
| 2168 | 2733 i = 0; |
| 2734 | |
| 2735 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) | |
| 462 | 2736 { |
| 2168 | 2737 gtk_add_tab_item(image_instance, nb, XCAR(rest), |
| 2738 IMAGE_INSTANCE_FRAME(ii), i); | |
| 462 | 2739 } |
| 2740 | |
| 2741 /* Show all the new widgets we just added... */ | |
| 2742 gtk_widget_show_all (GTK_WIDGET (nb)); | |
| 2743 } | |
| 2744 } | |
| 2745 | |
| 2746 /* Possibly update the face. */ | |
| 2747 #if 0 | |
| 2748 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) | |
| 2749 || | |
| 2750 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed | |
| 2751 || | |
| 2752 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) | |
| 2753 { | |
| 2754 update_tab_widget_face (wv, ii, | |
| 2755 IMAGE_INSTANCE_FRAME (ii)); | |
| 2756 } | |
| 2757 #endif | |
| 2758 } | |
| 2759 #endif /* HAVE_WIDGETS */ | |
| 2760 | |
| 2761 | |
| 2762 /************************************************************************/ | |
| 2763 /* initialization */ | |
| 2764 /************************************************************************/ | |
| 2765 void | |
| 2766 syms_of_glyphs_gtk (void) | |
| 2767 { | |
| 2768 #ifdef HAVE_WIDGETS | |
| 563 | 2769 DEFSYMBOL (Qgtk_widget_instantiate_internal); |
| 2770 DEFSYMBOL (Qgtk_widget_property_internal); | |
| 2771 DEFSYMBOL (Qgtk_widget_redisplay_internal); | |
| 2772 DEFSYMBOL (Qgtk_widget_set_style); | |
| 462 | 2773 #endif |
| 2774 } | |
| 2775 | |
| 2776 void | |
| 2777 console_type_create_glyphs_gtk (void) | |
| 2778 { | |
| 2779 /* image methods */ | |
| 2780 CONSOLE_HAS_METHOD (gtk, print_image_instance); | |
| 2781 CONSOLE_HAS_METHOD (gtk, finalize_image_instance); | |
| 2782 CONSOLE_HAS_METHOD (gtk, image_instance_equal); | |
| 2783 CONSOLE_HAS_METHOD (gtk, image_instance_hash); | |
| 2784 CONSOLE_HAS_METHOD (gtk, colorize_image_instance); | |
| 2785 CONSOLE_HAS_METHOD (gtk, init_image_instance_from_eimage); | |
| 2786 CONSOLE_HAS_METHOD (gtk, locate_pixmap_file); | |
| 2787 CONSOLE_HAS_METHOD (gtk, unmap_subwindow); | |
| 2788 CONSOLE_HAS_METHOD (gtk, map_subwindow); | |
| 2789 CONSOLE_HAS_METHOD (gtk, redisplay_widget); | |
| 2790 CONSOLE_HAS_METHOD (gtk, redisplay_subwindow); | |
| 2791 } | |
| 2792 | |
| 2793 void | |
| 2794 image_instantiator_format_create_glyphs_gtk (void) | |
| 2795 { | |
| 2796 IIFORMAT_VALID_CONSOLE (gtk, nothing); | |
| 2797 IIFORMAT_VALID_CONSOLE (gtk, string); | |
| 2798 #ifdef HAVE_WIDGETS | |
| 2799 IIFORMAT_VALID_CONSOLE (gtk, layout); | |
| 2800 #endif | |
| 2801 IIFORMAT_VALID_CONSOLE (gtk, formatted_string); | |
| 2802 IIFORMAT_VALID_CONSOLE (gtk, inherit); | |
| 2803 #ifdef HAVE_XPM | |
| 2804 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm); | |
| 2805 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate); | |
| 2806 #endif | |
| 2807 #ifdef HAVE_JPEG | |
| 2808 IIFORMAT_VALID_CONSOLE (gtk, jpeg); | |
| 2809 #endif | |
| 2810 #ifdef HAVE_TIFF | |
| 2811 IIFORMAT_VALID_CONSOLE (gtk, tiff); | |
| 2812 #endif | |
| 2813 #ifdef HAVE_PNG | |
| 2814 IIFORMAT_VALID_CONSOLE (gtk, png); | |
| 2815 #endif | |
| 2816 #ifdef HAVE_GIF | |
| 2817 IIFORMAT_VALID_CONSOLE (gtk, gif); | |
| 2818 #endif | |
| 2819 | |
| 2820 INITIALIZE_DEVICE_IIFORMAT (gtk, subwindow); | |
| 2821 IIFORMAT_HAS_DEVMETHOD (gtk, subwindow, instantiate); | |
| 2822 | |
| 2823 #ifdef HAVE_WIDGETS | |
| 2824 /* layout widget */ | |
| 2825 INITIALIZE_DEVICE_IIFORMAT (gtk, native_layout); | |
| 2826 IIFORMAT_HAS_DEVMETHOD (gtk, native_layout, instantiate); | |
| 2827 | |
| 2828 /* button widget */ | |
| 2829 INITIALIZE_DEVICE_IIFORMAT (gtk, button); | |
| 2830 IIFORMAT_HAS_DEVMETHOD (gtk, button, property); | |
| 2831 IIFORMAT_HAS_DEVMETHOD (gtk, button, instantiate); | |
| 2832 IIFORMAT_HAS_DEVMETHOD (gtk, button, redisplay); | |
| 2168 | 2833 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, button, query_geometry, widget); |
| 462 | 2834 /* general widget methods. */ |
| 2835 INITIALIZE_DEVICE_IIFORMAT (gtk, widget); | |
| 2836 IIFORMAT_HAS_DEVMETHOD (gtk, widget, property); | |
| 2168 | 2837 IIFORMAT_HAS_DEVMETHOD (gtk, widget, query_geometry); |
| 462 | 2838 |
| 2839 /* progress gauge */ | |
| 2840 INITIALIZE_DEVICE_IIFORMAT (gtk, progress_gauge); | |
| 2841 IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, redisplay); | |
| 2842 IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, instantiate); | |
| 2168 | 2843 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, progress_gauge, query_geometry, widget); |
| 462 | 2844 /* text field */ |
| 2845 INITIALIZE_DEVICE_IIFORMAT (gtk, edit_field); | |
| 2846 IIFORMAT_HAS_DEVMETHOD (gtk, edit_field, instantiate); | |
| 2847 INITIALIZE_DEVICE_IIFORMAT (gtk, combo_box); | |
| 2848 IIFORMAT_HAS_DEVMETHOD (gtk, combo_box, instantiate); | |
| 2849 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, combo_box, redisplay, tab_control); | |
| 2850 /* tab control widget */ | |
| 2851 INITIALIZE_DEVICE_IIFORMAT (gtk, tab_control); | |
| 2852 IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, instantiate); | |
| 2853 IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, redisplay); | |
| 2168 | 2854 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, tab_control, query_geometry, widget); |
| 462 | 2855 /* label */ |
| 2856 INITIALIZE_DEVICE_IIFORMAT (gtk, label); | |
| 2857 IIFORMAT_HAS_DEVMETHOD (gtk, label, instantiate); | |
| 2858 #endif | |
| 2859 | |
| 2860 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font"); | |
| 2861 IIFORMAT_VALID_CONSOLE (gtk, cursor_font); | |
| 2862 | |
| 2863 IIFORMAT_HAS_METHOD (cursor_font, validate); | |
| 2864 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types); | |
| 2865 IIFORMAT_HAS_METHOD (cursor_font, instantiate); | |
| 2866 | |
| 2867 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string); | |
| 2868 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string); | |
| 2869 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string); | |
| 2870 | |
| 2871 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font"); | |
| 2872 IIFORMAT_VALID_CONSOLE (gtk, font); | |
| 2873 | |
| 2874 IIFORMAT_HAS_METHOD (font, validate); | |
| 2875 IIFORMAT_HAS_METHOD (font, possible_dest_types); | |
| 2876 IIFORMAT_HAS_METHOD (font, instantiate); | |
| 2877 | |
| 2878 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); | |
| 2879 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); | |
| 2880 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); | |
| 2881 | |
| 2882 #ifdef HAVE_XPM | |
| 2883 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm); | |
| 2884 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate); | |
| 2885 #endif | |
| 2886 | |
| 2887 #ifdef HAVE_XFACE | |
| 2888 INITIALIZE_DEVICE_IIFORMAT (gtk, xface); | |
| 2889 IIFORMAT_HAS_DEVMETHOD (gtk, xface, instantiate); | |
| 2890 #endif | |
| 2891 | |
| 2892 INITIALIZE_DEVICE_IIFORMAT (gtk, xbm); | |
| 2893 IIFORMAT_HAS_DEVMETHOD (gtk, xbm, instantiate); | |
| 2894 IIFORMAT_VALID_CONSOLE (gtk, xbm); | |
| 2895 | |
| 2896 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource, "gtk-resource"); | |
| 2897 IIFORMAT_VALID_CONSOLE (gtk, gtk_resource); | |
| 2898 | |
| 2899 IIFORMAT_HAS_METHOD (gtk_resource, validate); | |
| 2900 IIFORMAT_HAS_METHOD (gtk_resource, normalize); | |
| 2901 IIFORMAT_HAS_METHOD (gtk_resource, possible_dest_types); | |
| 2902 IIFORMAT_HAS_METHOD (gtk_resource, instantiate); | |
| 2903 | |
| 2904 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_resource_type, check_valid_resource_symbol); | |
| 2905 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_resource_id, check_valid_resource_id); | |
| 2906 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_file, check_valid_string); | |
| 2907 | |
| 2908 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect, "autodetect"); | |
| 2909 IIFORMAT_VALID_CONSOLE (gtk, autodetect); | |
| 2910 | |
| 2911 IIFORMAT_HAS_METHOD (autodetect, validate); | |
| 2912 IIFORMAT_HAS_METHOD (autodetect, normalize); | |
| 2913 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types); | |
| 2914 IIFORMAT_HAS_METHOD (autodetect, instantiate); | |
| 2915 | |
| 2916 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string); | |
| 2917 } | |
| 2918 | |
| 2919 void | |
| 2920 vars_of_glyphs_gtk (void) | |
| 2921 { | |
| 2922 #ifdef HAVE_XFACE | |
| 2923 Fprovide (Qxface); | |
| 2924 #endif | |
| 2925 | |
| 2926 DEFVAR_LISP ("gtk-bitmap-file-path", &Vgtk_bitmap_file_path /* | |
| 2927 A list of the directories in which X bitmap files may be found. | |
| 2928 If nil, this is initialized from the "*bitmapFilePath" resource. | |
| 2929 This is used by the `make-image-instance' function (however, note that if | |
| 2930 the environment variable XBMLANGPATH is set, it is consulted first). | |
| 2931 */ ); | |
| 2932 Vgtk_bitmap_file_path = Qnil; | |
| 2933 } | |
| 2934 | |
| 2935 void | |
| 2936 complex_vars_of_glyphs_gtk (void) | |
| 2937 { | |
| 2938 #define BUILD_GLYPH_INST(variable, name) \ | |
| 2939 Fadd_spec_to_specifier \ | |
| 2940 (GLYPH_IMAGE (XGLYPH (variable)), \ | |
| 2941 vector3 (Qxbm, Q_data, \ | |
| 2942 list3 (make_int (name##_width), \ | |
| 2943 make_int (name##_height), \ | |
| 2054 | 2944 make_ext_string ((Extbyte*) name##_bits, \ |
| 462 | 2945 sizeof (name##_bits), \ |
| 2946 Qbinary))), \ | |
| 2947 Qglobal, Qgtk, Qnil) | |
| 2948 | |
| 2949 BUILD_GLYPH_INST (Vtruncation_glyph, truncator); | |
| 2950 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer); | |
| 2951 BUILD_GLYPH_INST (Vxemacs_logo, xemacs); | |
| 2952 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll); | |
| 2953 | |
| 2954 #undef BUILD_GLYPH_INST | |
| 2955 } | |
| 2956 | |
| 2957 /* X specific crap */ | |
| 2958 #include <gdk/gdkx.h> | |
| 2959 /* #### Should remove all this X specific stuff when GTK/GDK matures a | |
| 2960 bit more and provides an abstraction for it. */ | |
| 2961 static int | |
| 2962 gtk_colorize_image_instance (Lisp_Object image_instance, | |
| 2963 Lisp_Object foreground, Lisp_Object background) | |
| 2964 { | |
| 2965 struct Lisp_Image_Instance *p; | |
| 2966 | |
| 2967 p = XIMAGE_INSTANCE (image_instance); | |
| 2968 | |
| 2969 switch (IMAGE_INSTANCE_TYPE (p)) | |
| 2970 { | |
| 2971 case IMAGE_MONO_PIXMAP: | |
| 2972 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP; | |
| 2973 /* Make sure there aren't two pointers to the same mask, causing | |
| 2974 it to get freed twice. */ | |
|
4433
1bf48c59700e
Fix old use of rvalue on lhs to placate gcc >4.0.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4252
diff
changeset
|
2975 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; |
| 462 | 2976 break; |
| 2977 | |
| 2978 default: | |
| 2979 return 0; | |
| 2980 } | |
| 2981 | |
| 2982 { | |
| 2983 GdkWindow *draw = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))); | |
| 2984 GdkPixmap *new_pxmp = gdk_pixmap_new (draw, | |
| 2985 IMAGE_INSTANCE_PIXMAP_WIDTH (p), | |
| 2986 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), | |
| 2987 DEVICE_GTK_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))); | |
| 2988 GdkGCValues gcv; | |
| 2989 GdkGC *gc; | |
| 2990 | |
| 2991 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground)); | |
| 2992 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background)); | |
| 2054 | 2993 gc = gdk_gc_new_with_values (new_pxmp, &gcv, |
| 2994 (GdkGCValuesMask) (GDK_GC_BACKGROUND | GDK_GC_FOREGROUND)); | |
| 462 | 2995 |
| 2996 XCopyPlane (GDK_WINDOW_XDISPLAY (draw), | |
| 2997 GDK_WINDOW_XWINDOW (IMAGE_INSTANCE_GTK_PIXMAP (p)), | |
| 2998 GDK_WINDOW_XWINDOW (new_pxmp), | |
| 2999 GDK_GC_XGC (gc), 0, 0, | |
| 3000 IMAGE_INSTANCE_PIXMAP_WIDTH (p), | |
| 3001 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), | |
| 3002 0, 0, 1); | |
| 3003 | |
| 3004 gdk_gc_destroy (gc); | |
| 3005 IMAGE_INSTANCE_GTK_PIXMAP (p) = new_pxmp; | |
| 3006 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = DEVICE_GTK_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p))); | |
| 3007 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground; | |
| 3008 IMAGE_INSTANCE_PIXMAP_BG (p) = background; | |
| 3009 return 1; | |
| 3010 } | |
| 3011 } |
