comparison src/toolbar-x.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 84b14dcb0985
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* toolbar implementation -- X interface.
2 Copyright (C) 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 /* Synched up with: Not in FSF. */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "console-x.h"
30 #include "glyphs-x.h"
31 #include "objects-x.h"
32 #include "EmacsFrame.h"
33 #include "EmacsFrameP.h"
34
35 #include "faces.h"
36 #include "frame.h"
37 #include "toolbar.h"
38 #include "window.h"
39
40 static void
41 x_draw_blank_toolbar_button (struct frame *f, int x, int y, int width,
42 int height, int threed, int border_width,
43 int vertical)
44 {
45 struct device *d = XDEVICE (f->device);
46 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
47 int shadow_thickness = ef->emacs_frame.toolbar_shadow_thickness;
48 int sx = x, sy = y, swidth = width, sheight = height;
49
50 Display *dpy = DEVICE_X_DISPLAY (d);
51 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
52 GC top_shadow_gc, bottom_shadow_gc, background_gc;
53
54 background_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
55
56 if (threed)
57 {
58 top_shadow_gc = FRAME_X_TOOLBAR_TOP_SHADOW_GC (f);
59 bottom_shadow_gc = FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f);
60 }
61 else
62 {
63 top_shadow_gc = background_gc;
64 bottom_shadow_gc = background_gc;
65 }
66
67 if (vertical)
68 {
69 sx += border_width;
70 swidth -= 2 * border_width;
71 }
72 else
73 {
74 sy += border_width;
75 sheight -= 2 * border_width;
76 }
77
78 /* Draw the outline. */
79 x_output_shadows (f, sx, sy, swidth, sheight, top_shadow_gc,
80 bottom_shadow_gc, background_gc, shadow_thickness,
81 EDGE_ALL);
82
83 /* Blank the middle. */
84 XFillRectangle (dpy, x_win, background_gc, sx + shadow_thickness,
85 sy + shadow_thickness, swidth - shadow_thickness * 2,
86 sheight - shadow_thickness * 2);
87
88 /* Do the border */
89 XFillRectangle (dpy, x_win, background_gc, x, y,
90 (vertical ? border_width : width),
91 (vertical ? height : border_width));
92 XFillRectangle (dpy, x_win, background_gc,
93 (vertical ? sx + swidth : x),
94 (vertical ? y : sy + sheight),
95 (vertical ? border_width : width),
96 (vertical ? height : border_width));
97 }
98
99 static void
100 x_output_toolbar_button (struct frame *f, Lisp_Object button)
101 {
102 struct device *d = XDEVICE (f->device);
103 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
104 int shadow_thickness = ef->emacs_frame.toolbar_shadow_thickness;
105 int x_adj, y_adj, width_adj, height_adj;
106
107 Display *dpy = DEVICE_X_DISPLAY (d);
108 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
109 GC top_shadow_gc, bottom_shadow_gc, background_gc;
110 Lisp_Object instance, frame, window, glyph;
111 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
112 struct Lisp_Image_Instance *p;
113 struct window *w;
114 int vertical = tb->vertical;
115 int border_width = tb->border_width;
116
117 if (vertical)
118 {
119 x_adj = border_width;
120 width_adj = - 2 * border_width;
121 y_adj = 0;
122 height_adj = 0;
123 }
124 else
125 {
126 x_adj = 0;
127 width_adj = 0;
128 y_adj = border_width;
129 height_adj = - 2 * border_width;
130 }
131
132 XSETFRAME (frame, f);
133 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
134 w = XWINDOW (window);
135
136 glyph = get_toolbar_button_glyph (w, tb);
137
138 if (tb->enabled)
139 {
140 if (tb->down)
141 {
142 top_shadow_gc = FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f);
143 bottom_shadow_gc = FRAME_X_TOOLBAR_TOP_SHADOW_GC (f);
144 }
145 else
146 {
147 top_shadow_gc = FRAME_X_TOOLBAR_TOP_SHADOW_GC (f);
148 bottom_shadow_gc = FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f);
149 }
150 }
151 else
152 {
153 top_shadow_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
154 bottom_shadow_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
155 }
156 background_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
157
158 /* Draw the outline. */
159 x_output_shadows (f, tb->x + x_adj, tb->y + y_adj,
160 tb->width + width_adj, tb->height + height_adj,
161 top_shadow_gc,
162 bottom_shadow_gc, background_gc, shadow_thickness,
163 EDGE_ALL);
164
165 /* Clear the pixmap area. */
166 XFillRectangle (dpy, x_win, background_gc, tb->x + x_adj + shadow_thickness,
167 tb->y + y_adj + shadow_thickness,
168 tb->width + width_adj - shadow_thickness * 2,
169 tb->height + height_adj - shadow_thickness * 2);
170
171 /* Do the border. */
172 XFillRectangle (dpy, x_win, background_gc, tb->x, tb->y,
173 (vertical ? border_width : tb->width),
174 (vertical ? tb->height : border_width));
175
176 XFillRectangle (dpy, x_win, background_gc,
177 (vertical ? tb->x + tb->width - border_width : tb->x),
178 (vertical ? tb->y : tb->y + tb->height - border_width),
179 (vertical ? border_width : tb->width),
180 (vertical ? tb->height : border_width));
181
182 background_gc = FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f);
183
184 /* #### It is currently possible for users to trash us by directly
185 changing the toolbar glyphs. Avoid crashing in that case. */
186 if (GLYPHP (glyph))
187 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
188 else
189 instance = Qnil;
190
191 if (IMAGE_INSTANCEP (instance))
192 {
193 int width = tb->width + width_adj - shadow_thickness * 2;
194 int height = tb->height + height_adj - shadow_thickness * 2;
195 int x_offset = x_adj + shadow_thickness;
196 int y_offset = y_adj + shadow_thickness;
197
198 p = XIMAGE_INSTANCE (instance);
199
200 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p))
201 {
202 if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p))
203 {
204 x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p))
205 / 2);
206 width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
207 }
208 if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
209 {
210 y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
211 / 2);
212 height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
213 }
214
215 x_output_x_pixmap (f, XIMAGE_INSTANCE (instance), tb->x + x_offset,
216 tb->y + y_offset, 0, 0, width, height,
217 0, 0, background_gc);
218 }
219 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT)
220 {
221 /* #### We need to make the face used configurable. */
222 struct face_cachel *cachel =
223 WINDOW_FACE_CACHEL (w, DEFAULT_INDEX);
224 struct display_line dl;
225 Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p);
226 unsigned char charsets[NUM_LEADING_BYTES];
227 Emchar_dynarr *buf;
228 struct font_metric_info fm;
229
230 /* This could be true if we were called via the Expose event
231 handler. Mark the button as dirty and return
232 immediately. */
233 if (f->window_face_cache_reset)
234 {
235 tb->dirty = 1;
236 MARK_TOOLBAR_CHANGED;
237 return;
238 }
239 buf = Dynarr_new (Emchar);
240 convert_bufbyte_string_into_emchar_dynarr
241 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
242 find_charsets_in_emchar_string (charsets, Dynarr_atp (buf, 0),
243 Dynarr_length (buf));
244 ensure_face_cachel_complete (cachel, window, charsets);
245 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
246
247 dl.ascent = fm.ascent;
248 dl.descent = fm.descent;
249 dl.ypos = tb->y + y_offset + fm.ascent;
250
251 if (fm.ascent + fm.descent <= height)
252 {
253 dl.ypos += (height - fm.ascent - fm.descent) / 2;
254 dl.clip = 0;
255 }
256 else
257 {
258 dl.clip = fm.ascent + fm.descent - height;
259 }
260
261 x_output_string (w, &dl, buf, tb->x + x_offset, 0, 0, width,
262 DEFAULT_INDEX, 0, 0, 0, 0);
263 Dynarr_free (buf);
264 }
265
266 /* We silently ignore the image if it isn't a pixmap or text. */
267 }
268
269 tb->dirty = 0;
270 }
271
272 static int
273 x_get_button_size (struct frame *f, Lisp_Object window,
274 struct toolbar_button *tb, int vert, int pos)
275 {
276 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
277 int shadow_thickness = ef->emacs_frame.toolbar_shadow_thickness;
278 int size;
279
280 if (tb->blank)
281 {
282 if (!NILP (tb->down_glyph))
283 size = XINT (tb->down_glyph);
284 else
285 size = DEFAULT_TOOLBAR_BLANK_SIZE;
286 }
287 else
288 {
289 struct window *w = XWINDOW (window);
290 Lisp_Object glyph = get_toolbar_button_glyph (w, tb);
291
292 /* Unless, of course, the user has done something stupid like
293 change the glyph out from under us. Use a blank placeholder
294 in that case. */
295 if (NILP (glyph))
296 return XINT (f->toolbar_size[pos]);
297
298 if (vert)
299 size = glyph_height (glyph, Vdefault_face, 0, window);
300 else
301 size = glyph_width (glyph, Vdefault_face, 0, window);
302 }
303
304 if (!size)
305 {
306 /* If the glyph doesn't have a size we'll insert a blank
307 placeholder instead. */
308 return XINT (f->toolbar_size[pos]);
309 }
310
311 size += shadow_thickness * 2;
312
313 return (size);
314 }
315
316 #define X_OUTPUT_BUTTONS_LOOP(left) \
317 do { \
318 while (!NILP (button)) \
319 { \
320 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); \
321 int size, height, width; \
322 \
323 if (left && tb->pushright) \
324 break; \
325 \
326 size = x_get_button_size (f, window, tb, vert, pos); \
327 \
328 if (vert) \
329 { \
330 width = bar_width; \
331 if (y + size > max_pixpos) \
332 height = max_pixpos - y; \
333 else \
334 height = size; \
335 } \
336 else \
337 { \
338 if (x + size > max_pixpos) \
339 width = max_pixpos - x; \
340 else \
341 width = size; \
342 height = bar_height; \
343 } \
344 \
345 if (tb->x != x \
346 || tb->y != y \
347 || tb->width != width \
348 || tb->height != height \
349 || tb->dirty) \
350 { \
351 if (width && height) \
352 { \
353 tb->x = x; \
354 tb->y = y; \
355 tb->width = width; \
356 tb->height = height; \
357 tb->border_width = border_width; \
358 tb->vertical = vert; \
359 \
360 if (tb->blank || NILP (tb->up_glyph)) \
361 { \
362 int threed = (EQ (Qt, tb->up_glyph) ? 1 : 0); \
363 x_draw_blank_toolbar_button (f, x, y, width, \
364 height, threed, \
365 border_width, vert); \
366 } \
367 else \
368 x_output_toolbar_button (f, button); \
369 } \
370 } \
371 \
372 if (vert) \
373 y += height; \
374 else \
375 x += width; \
376 \
377 if ((vert && y == max_pixpos) || (!vert && x == max_pixpos)) \
378 button = Qnil; \
379 else \
380 button = tb->next; \
381 } \
382 } while (0)
383
384 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \
385 do { \
386 switch (pos) \
387 { \
388 case TOP_TOOLBAR: \
389 (frame)->top_toolbar_was_visible = flag; \
390 break; \
391 case BOTTOM_TOOLBAR: \
392 (frame)->bottom_toolbar_was_visible = flag; \
393 break; \
394 case LEFT_TOOLBAR: \
395 (frame)->left_toolbar_was_visible = flag; \
396 break; \
397 case RIGHT_TOOLBAR: \
398 (frame)->right_toolbar_was_visible = flag; \
399 break; \
400 default: \
401 abort (); \
402 } \
403 } while (0)
404
405 static void
406 x_output_toolbar (struct frame *f, enum toolbar_pos pos)
407 {
408 struct device *d = XDEVICE (f->device);
409 int x, y, bar_width, bar_height, vert;
410 int max_pixpos, right_size, right_start, blank_size;
411 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
412 Lisp_Object button, window;
413 Display *dpy = DEVICE_X_DISPLAY (d);
414 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
415 GC background_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
416
417 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1);
418 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
419
420 /* Do the border */
421 XFillRectangle (dpy, x_win, background_gc, x, y,
422 (vert ? bar_width : border_width),
423 (vert ? border_width : bar_height));
424 XFillRectangle (dpy, x_win, background_gc,
425 (vert ? x : x + bar_width - border_width),
426 (vert ? y + bar_height - border_width : y),
427 (vert ? bar_width : border_width),
428 (vert ? border_width : bar_height));
429
430 if (vert)
431 {
432 max_pixpos = y + bar_height - border_width;
433 y += border_width;
434 }
435 else
436 {
437 max_pixpos = x + bar_width - border_width;
438 x += border_width;
439 }
440
441 button = FRAME_TOOLBAR_BUTTONS (f, pos);
442 right_size = 0;
443
444 /* First loop over all of the buttons to determine how much room we
445 need for left hand and right hand buttons. This loop will also
446 make sure that all instances are instantiated so when we actually
447 output them they will come up immediately. */
448 while (!NILP (button))
449 {
450 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
451 int size = x_get_button_size (f, window, tb, vert, pos);
452
453 if (tb->pushright)
454 right_size += size;
455
456 button = tb->next;
457 }
458
459 button = FRAME_TOOLBAR_BUTTONS (f, pos);
460
461 /* Loop over the left buttons, updating and outputting them. */
462 X_OUTPUT_BUTTONS_LOOP (1);
463
464 /* Now determine where the right buttons start. */
465 right_start = max_pixpos - right_size;
466 if (right_start < (vert ? y : x))
467 right_start = (vert ? y : x);
468
469 /* Output the blank which goes from the end of the left buttons to
470 the start of the right. */
471 blank_size = right_start - (vert ? y : x);
472 if (blank_size)
473 {
474 int height, width;
475
476 if (vert)
477 {
478 width = bar_width;
479 height = blank_size;
480 }
481 else
482 {
483 width = blank_size;
484 height = bar_height;
485 }
486
487 /*
488 * Use a 3D pushright separator only if there isn't a toolbar
489 * border. A flat separator meshes with the border and looks
490 * better.
491 */
492 x_draw_blank_toolbar_button (f, x, y, width, height, !border_width,
493 border_width, vert);
494
495 if (vert)
496 y += height;
497 else
498 x += width;
499 }
500
501 /* Loop over the right buttons, updating and outputting them. */
502 X_OUTPUT_BUTTONS_LOOP (0);
503
504 if (!vert)
505 {
506 Lisp_Object frame;
507
508 XSETFRAME (frame, f);
509 redisplay_clear_region (frame,
510 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1,
511 bar_height);
512 }
513
514 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
515
516 XFlush (DEVICE_X_DISPLAY (d));
517 }
518
519 static void
520 x_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change)
521 {
522 Lisp_Object frame;
523 struct device *d = XDEVICE (f->device);
524 int x, y, width, height, vert;
525
526 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1);
527 XSETFRAME (frame, f);
528
529 /* The thickness_change parameter is used by the toolbar resize routines
530 to clear any excess toolbar if the size shrinks. */
531 if (thickness_change < 0)
532 {
533 if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR)
534 {
535 x = x + width + thickness_change;
536 width = -thickness_change;
537 }
538 else
539 {
540 y = y + height + thickness_change;
541 height = -thickness_change;
542 }
543 }
544
545 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0);
546
547 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height);
548 XFlush (DEVICE_X_DISPLAY (d));
549 }
550
551 static void
552 x_output_frame_toolbars (struct frame *f)
553 {
554 assert (FRAME_X_P (f));
555
556 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
557 x_output_toolbar (f, TOP_TOOLBAR);
558 else if (f->top_toolbar_was_visible)
559 x_clear_toolbar (f, TOP_TOOLBAR, 0);
560
561 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
562 x_output_toolbar (f, BOTTOM_TOOLBAR);
563 else if (f->bottom_toolbar_was_visible)
564 x_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
565
566 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
567 x_output_toolbar (f, LEFT_TOOLBAR);
568 else if (f->left_toolbar_was_visible)
569 x_clear_toolbar (f, LEFT_TOOLBAR, 0);
570
571 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
572 x_output_toolbar (f, RIGHT_TOOLBAR);
573 else if (f->right_toolbar_was_visible)
574 x_clear_toolbar (f, RIGHT_TOOLBAR, 0);
575 }
576
577 static void
578 x_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y,
579 int width, int height)
580 {
581 int bar_x, bar_y, bar_width, bar_height, vert;
582 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos);
583
584 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height,
585 &vert, 1);
586
587 if (((y + height) < bar_y) || (y > (bar_y + bar_height)))
588 return;
589 if (((x + width) < bar_x) || (x > (bar_x + bar_width)))
590 return;
591
592 while (!NILP (button))
593 {
594 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
595
596 if (vert)
597 {
598 if (((tb->y + tb->height) > y) && (tb->y < (y + height)))
599 tb->dirty = 1;
600
601 /* If this is true we have gone past the exposed region. */
602 if (tb->y > (y + height))
603 break;
604 }
605 else
606 {
607 if (((tb->x + tb->width) > x) && (tb->x < (x + width)))
608 tb->dirty = 1;
609
610 /* If this is true we have gone past the exposed region. */
611 if (tb->x > (x + width))
612 break;
613 }
614
615 button = tb->next;
616 }
617
618 /* Even if none of the buttons is in the area, the blank region at
619 the very least must be because the first thing we did is verify
620 that some portion of the toolbar is in the exposed region. */
621 x_output_toolbar (f, pos);
622 }
623
624 static void
625 x_redraw_exposed_toolbars (struct frame *f, int x, int y, int width,
626 int height)
627 {
628 assert (FRAME_X_P (f));
629
630 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
631 x_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height);
632
633 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
634 x_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height);
635
636 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
637 x_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height);
638
639 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
640 x_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height);
641 }
642
643 static void
644 x_redraw_frame_toolbars (struct frame *f)
645 {
646 /* There are certain startup paths that lead to update_EmacsFrame in
647 faces.c being called before a new frame is fully initialized. In
648 particular before we have actually mapped it. That routine can
649 call this one. So, we need to make sure that the frame is
650 actually ready before we try and draw all over it. */
651
652 if (XtIsRealized (FRAME_X_SHELL_WIDGET (f)))
653 x_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f),
654 FRAME_PIXHEIGHT (f));
655 }
656
657
658 static void
659 x_initialize_frame_toolbar_gcs (struct frame *f)
660 {
661 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
662 EmacsFramePart *efp = &(ef->emacs_frame);
663 XGCValues gcv;
664 unsigned long flags = (GCForeground | GCBackground | GCGraphicsExposures);
665
666 /*
667 * If backgroundToolBarColor is specified, use it.
668 * Otherwise use the background resource.
669 */
670 if (efp->background_toolbar_pixel == (Pixel) (-1))
671 efp->background_toolbar_pixel = efp->background_pixel;
672
673 /*
674 * ####
675 * If foregroundToolBarColor is specified, use it.
676 * Otherwise use the foreground resource.
677 *
678 * The foreground pixel is currently unused, but will likely be
679 * used when toolbar captions are generated by the toolbar code
680 * instead being incorporated into the icon image.
681 */
682 if (efp->foreground_toolbar_pixel == (Pixel) (-1))
683 efp->foreground_toolbar_pixel = efp->foreground_pixel;
684
685 gcv.foreground = efp->background_toolbar_pixel;
686 gcv.background = ef->core.background_pixel;
687 gcv.graphics_exposures = False;
688 FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f) =
689 XtGetGC ((Widget) ef, flags, &gcv);
690
691 if (efp->top_toolbar_shadow_pixel == efp->bottom_toolbar_shadow_pixel)
692 {
693 efp->top_toolbar_shadow_pixel = efp->background_toolbar_pixel;
694 efp->bottom_toolbar_shadow_pixel = efp->background_toolbar_pixel;
695 }
696
697 x_generate_shadow_pixels (f, &efp->top_toolbar_shadow_pixel,
698 &efp->bottom_toolbar_shadow_pixel,
699 efp->background_toolbar_pixel,
700 ef->core.background_pixel);
701
702 gcv.foreground = efp->top_toolbar_shadow_pixel;
703 gcv.background = ef->core.background_pixel;
704 gcv.graphics_exposures = False;
705 flags = GCForeground | GCBackground | GCGraphicsExposures;
706 if (efp->top_toolbar_shadow_pixmap)
707 {
708 gcv.fill_style = FillOpaqueStippled;
709 gcv.stipple = efp->top_toolbar_shadow_pixmap;
710 flags |= GCStipple | GCFillStyle;
711 }
712 FRAME_X_TOOLBAR_TOP_SHADOW_GC (f) = XtGetGC ((Widget) ef, flags, &gcv);
713
714 gcv.foreground = efp->bottom_toolbar_shadow_pixel;
715 gcv.background = ef->core.background_pixel;
716 gcv.graphics_exposures = False;
717 flags = GCForeground | GCBackground | GCGraphicsExposures;
718 if (efp->bottom_toolbar_shadow_pixmap)
719 {
720 gcv.fill_style = FillOpaqueStippled;
721 gcv.stipple = efp->bottom_toolbar_shadow_pixmap;
722 flags |= GCStipple | GCFillStyle;
723 }
724 FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f) = XtGetGC ((Widget) ef, flags, &gcv);
725
726 #ifdef HAVE_XPM
727 FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f) =
728 FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
729 #else
730 {
731 struct device *d = XDEVICE (f->device);
732 Display *dpy = DEVICE_X_DISPLAY (d);
733
734 gcv.background = WhitePixelOfScreen (DefaultScreenOfDisplay (dpy));
735 gcv.foreground = BlackPixelOfScreen (DefaultScreenOfDisplay (dpy));
736 gcv.graphics_exposures = False;
737 flags = GCForeground | GCBackground | GCGraphicsExposures;
738 FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f) =
739 XtGetGC ((Widget) ef, flags, &gcv);
740 }
741 #endif
742 }
743
744 static void
745 x_release_frame_toolbar_gcs (struct frame *f)
746 {
747 Widget ew = (Widget) FRAME_X_TEXT_WIDGET (f);
748 XtReleaseGC (ew, FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f));
749 /* If compiled with XPM support, this is a pointer to the same GC as
750 FRAME_X_BLANK_BACKGROUND_GC so we need to make sure we don't
751 release it twice. */
752 #ifndef HAVE_XPM
753 XtReleaseGC (ew, FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f));
754 #endif
755 XtReleaseGC (ew, FRAME_X_TOOLBAR_TOP_SHADOW_GC (f));
756 XtReleaseGC (ew, FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f));
757
758 /* Seg fault if we try and use these again. */
759 FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f) = (GC) - 1;
760 FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f) = (GC) - 1;
761 FRAME_X_TOOLBAR_TOP_SHADOW_GC (f) = (GC) - 1;
762 FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f) = (GC) - 1;
763 }
764
765 static void
766 x_initialize_frame_toolbars (struct frame *f)
767 {
768 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
769
770 if (ef->emacs_frame.toolbar_shadow_thickness < MINIMUM_SHADOW_THICKNESS)
771 Xt_SET_VALUE (FRAME_X_TEXT_WIDGET (f),
772 XtNtoolBarShadowThickness, MINIMUM_SHADOW_THICKNESS);
773
774 x_initialize_frame_toolbar_gcs (f);
775 }
776
777 /* This only calls one function but we go ahead and create this in
778 case we ever do decide that we need to do more work. */
779 static void
780 x_free_frame_toolbars (struct frame *f)
781 {
782 x_release_frame_toolbar_gcs (f);
783 }
784
785
786 /************************************************************************/
787 /* initialization */
788 /************************************************************************/
789
790 void
791 console_type_create_toolbar_x (void)
792 {
793 CONSOLE_HAS_METHOD (x, output_frame_toolbars);
794 CONSOLE_HAS_METHOD (x, initialize_frame_toolbars);
795 CONSOLE_HAS_METHOD (x, free_frame_toolbars);
796 CONSOLE_HAS_METHOD (x, output_toolbar_button);
797 CONSOLE_HAS_METHOD (x, redraw_exposed_toolbars);
798 CONSOLE_HAS_METHOD (x, redraw_frame_toolbars);
799 }