Mercurial > hg > xemacs-beta
comparison src/toolbar-common.c @ 713:c2c346111c9a
[xemacs-hg @ 2001-12-23 01:11:00 by wmperry]
New common redisplay-based toolbar code.
author | wmperry |
---|---|
date | Sun, 23 Dec 2001 01:11:00 +0000 |
parents | |
children | 02339d4ebed4 |
comparison
equal
deleted
inserted
replaced
712:2d3184c89f71 | 713:c2c346111c9a |
---|---|
1 /* toolbar implementation -- Generic redisplay 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 "faces.h" | |
30 #include "frame.h" | |
31 #include "toolbar.h" | |
32 #include "window.h" | |
33 | |
34 /* Only a very few things need to differ based on the toolkit used. | |
35 ** | |
36 ** Some of the routines used assert(FRAME_yyy_P(f)) checks, this is | |
37 ** now abstracted into __INTERNAL_APPROPRIATENESS_CHECK(). When we | |
38 ** add new window systems that use this code, we should either add a | |
39 ** new case here, or just remove the checks completely. | |
40 ** | |
41 ** At least for X & GTK redraw_frame_toolbars() might end up getting | |
42 ** called before we are completely initialized. To avoid this, we use | |
43 ** the __INTERNAL_MAPPED_P(f) macro, that should return 0 if we should | |
44 ** not draw the toolbars yet. When we add new window systems that use | |
45 ** this code, we should add a new case here, if they need it. | |
46 ** | |
47 ** When clearing the toolbar, it is nice to flush the drawing queue. | |
48 ** Use __INTERNAL_FLUSH to do this. It is passed a device. | |
49 */ | |
50 #if defined(HAVE_GTK) | |
51 #include "console-gtk.h" | |
52 #define __INTERNAL_MAPPED_P(f) GTK_WIDGET_REALIZED (FRAME_GTK_TEXT_WIDGET (f)) | |
53 #define __INTERNAL_FLUSH(d) gdk_flush() | |
54 #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_GTK_P (f)) | |
55 #elif defined(HAVE_X_WINDOWS) | |
56 #include "console-x.h" | |
57 #define __INTERNAL_MAPPED_P(f) XtIsRealized (FRAME_X_SHELL_WIDGET (f)) | |
58 #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_X_P (f)) | |
59 #define __INTERNAL_FLUSH(d) XFlush (DEVICE_X_DISPLAY (d)) | |
60 #else | |
61 #define __INTERNAL_MAPPED_P(f) abort() | |
62 #define __INTERNAL_APPROPRIATENESS_CHECK(f) abort() | |
63 #define __INTERNAL_FLUSH(f) abort() | |
64 #endif | |
65 | |
66 #include "toolbar-common.h" | |
67 | |
68 static void __prepare_button_area (struct frame *f, | |
69 struct toolbar_button *tb) | |
70 { | |
71 int sx = tb->x; | |
72 int sy = tb->y; | |
73 int swidth = tb->width; | |
74 int sheight = tb->height; | |
75 int border_width = tb->border_width; | |
76 int x_adj, width_adj, y_adj, height_adj; | |
77 struct device *d = XDEVICE (f->device); | |
78 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
79 struct window *w = XWINDOW (window); | |
80 int shadow_thickness = 2; | |
81 face_index toolbar_findex; | |
82 | |
83 if (tb->vertical) | |
84 { | |
85 x_adj = border_width; | |
86 width_adj = - 2 * border_width; | |
87 y_adj = height_adj = 0; | |
88 } | |
89 else | |
90 { | |
91 x_adj = width_adj = 0; | |
92 y_adj = border_width; | |
93 height_adj = - 2 * border_width; | |
94 } | |
95 | |
96 toolbar_findex = get_builtin_face_cache_index (w, Vtoolbar_face); | |
97 | |
98 /* Blank toolbar buttons that should be 3d will have EQ(tb->up_glyph, Qt) | |
99 ** Blank toolbar buttons that should be flat will have NILP (tb->up_glyph) | |
100 ** | |
101 ** Real toolbar buttons will check tb->enabled && tb->down | |
102 */ | |
103 if (EQ (Qt, tb->up_glyph)) | |
104 { | |
105 shadow_thickness = 2; | |
106 } | |
107 else if (NILP (tb->up_glyph)) | |
108 { | |
109 shadow_thickness = 0; | |
110 } | |
111 else | |
112 { | |
113 if (tb->enabled) | |
114 { | |
115 if (tb->down) | |
116 shadow_thickness = -2; | |
117 else | |
118 shadow_thickness = 2; | |
119 } | |
120 else | |
121 { | |
122 shadow_thickness = 0; | |
123 } | |
124 } | |
125 | |
126 /* Blank the entire area. */ | |
127 redisplay_clear_region (window, toolbar_findex, | |
128 sx + x_adj, sy + y_adj, | |
129 swidth + width_adj, | |
130 sheight + height_adj); | |
131 | |
132 /* Draw the outline. */ | |
133 if (shadow_thickness) | |
134 { | |
135 MAYBE_DEVMETH (d, bevel_area, | |
136 (w, toolbar_findex, sx + x_adj, | |
137 sy + y_adj, swidth + width_adj, | |
138 sheight + height_adj, abs(shadow_thickness), | |
139 EDGE_ALL, (shadow_thickness < 0) ? EDGE_BEVEL_IN : EDGE_BEVEL_OUT)); | |
140 } | |
141 | |
142 /* Handle the borders... */ | |
143 redisplay_clear_region (window, toolbar_findex, | |
144 sx, sy, | |
145 (tb->vertical ? border_width : swidth), | |
146 (tb->vertical ? sheight : border_width)); | |
147 redisplay_clear_region (window, toolbar_findex, | |
148 (tb->vertical ? sx + swidth : sx), | |
149 (tb->vertical ? sy : sy + sheight), | |
150 (tb->vertical ? border_width : swidth), | |
151 (tb->vertical ? sheight : border_width)); | |
152 } | |
153 | |
154 #define common_draw_blank_toolbar_button(f,tb) __prepare_button_area (f,tb) | |
155 | |
156 void | |
157 common_output_toolbar_button (struct frame *f, Lisp_Object button) | |
158 { | |
159 int shadow_thickness = 2; | |
160 int x_adj, y_adj, width_adj, height_adj; | |
161 struct device *d = XDEVICE (f->device); | |
162 Lisp_Object instance, frame, window, glyph; | |
163 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
164 struct Lisp_Image_Instance *p; | |
165 struct window *w; | |
166 int vertical = tb->vertical; | |
167 int border_width = tb->border_width; | |
168 face_index toolbar_findex; | |
169 | |
170 if (vertical) | |
171 { | |
172 x_adj = border_width; | |
173 width_adj = - 2 * border_width; | |
174 y_adj = 0; | |
175 height_adj = 0; | |
176 } | |
177 else | |
178 { | |
179 x_adj = 0; | |
180 width_adj = 0; | |
181 y_adj = border_width; | |
182 height_adj = - 2 * border_width; | |
183 } | |
184 | |
185 XSETFRAME (frame, f); | |
186 window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
187 w = XWINDOW (window); | |
188 | |
189 glyph = get_toolbar_button_glyph (w, tb); | |
190 | |
191 if (tb->enabled) | |
192 { | |
193 if (tb->down) | |
194 { | |
195 shadow_thickness = -2; | |
196 } | |
197 else | |
198 { | |
199 shadow_thickness = 2; | |
200 } | |
201 } | |
202 else | |
203 { | |
204 shadow_thickness = 0; | |
205 } | |
206 | |
207 toolbar_findex = get_builtin_face_cache_index (w, Vtoolbar_face); | |
208 | |
209 __prepare_button_area (f, tb); | |
210 | |
211 /* #### It is currently possible for users to trash us by directly | |
212 changing the toolbar glyphs. Avoid crashing in that case. */ | |
213 if (GLYPHP (glyph)) | |
214 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); | |
215 else | |
216 instance = Qnil; | |
217 | |
218 if (IMAGE_INSTANCEP (instance)) | |
219 { | |
220 int width = tb->width + width_adj - shadow_thickness * 2; | |
221 int height = tb->height + height_adj - shadow_thickness * 2; | |
222 int x_offset = x_adj + shadow_thickness; | |
223 int y_offset = y_adj + shadow_thickness; | |
224 | |
225 p = XIMAGE_INSTANCE (instance); | |
226 | |
227 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p)) | |
228 { | |
229 struct display_box db; | |
230 struct display_glyph_area dga; | |
231 | |
232 if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p)) | |
233 { | |
234 x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p)) | |
235 / 2); | |
236 width = IMAGE_INSTANCE_PIXMAP_WIDTH (p); | |
237 } | |
238 if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) | |
239 { | |
240 y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) | |
241 / 2); | |
242 height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); | |
243 } | |
244 | |
245 /* Draw exactly in the area specified... */ | |
246 db.xpos = tb->x + x_offset; | |
247 db.ypos = tb->y + y_offset; | |
248 db.width = width; | |
249 db.height = height; | |
250 | |
251 /* Display the whole glyph */ | |
252 dga.xoffset = 0; | |
253 dga.yoffset = 0; | |
254 dga.width = width; | |
255 dga.height = height; | |
256 | |
257 redisplay_output_pixmap (w, instance, | |
258 &db, &dga, | |
259 toolbar_findex, 0, 0, 0, 0); | |
260 } | |
261 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT) | |
262 { | |
263 /* #### We need to make the face used configurable. */ | |
264 struct face_cachel *cachel = | |
265 WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); | |
266 struct display_line dl; | |
267 Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p); | |
268 unsigned char charsets[NUM_LEADING_BYTES]; | |
269 Emchar_dynarr *buf; | |
270 struct font_metric_info fm; | |
271 | |
272 /* This could be true if we were called via the Expose event | |
273 handler. Mark the button as dirty and return | |
274 immediately. */ | |
275 if (f->window_face_cache_reset) | |
276 { | |
277 tb->dirty = 1; | |
278 MARK_TOOLBAR_CHANGED; | |
279 return; | |
280 } | |
281 buf = Dynarr_new (Emchar); | |
282 convert_intbyte_string_into_emchar_dynarr | |
283 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf); | |
284 find_charsets_in_emchar_string (charsets, Dynarr_atp (buf, 0), | |
285 Dynarr_length (buf)); | |
286 ensure_face_cachel_complete (cachel, window, charsets); | |
287 face_cachel_charset_font_metric_info (cachel, charsets, &fm); | |
288 | |
289 dl.ascent = fm.ascent; | |
290 dl.descent = fm.descent; | |
291 dl.ypos = tb->y + y_offset + fm.ascent; | |
292 | |
293 if (fm.ascent + fm.descent <= height) | |
294 { | |
295 dl.ypos += (height - fm.ascent - fm.descent) / 2; | |
296 dl.clip = 0; | |
297 } | |
298 else | |
299 { | |
300 dl.clip = fm.ascent + fm.descent - height; | |
301 } | |
302 | |
303 MAYBE_DEVMETH (d, output_string, | |
304 (w, &dl, buf, tb->x + x_offset, 0, 0, width, | |
305 toolbar_findex, 0, 0, 0, 0)); | |
306 Dynarr_free (buf); | |
307 } | |
308 | |
309 /* We silently ignore the image if it isn't a pixmap or text. */ | |
310 } | |
311 | |
312 tb->dirty = 0; | |
313 } | |
314 | |
315 static int | |
316 common_get_button_size (struct frame *f, Lisp_Object window, | |
317 struct toolbar_button *tb, int vert, int pos) | |
318 { | |
319 int shadow_thickness = 2; | |
320 int size; | |
321 | |
322 if (tb->blank) | |
323 { | |
324 if (!NILP (tb->down_glyph)) | |
325 size = XINT (tb->down_glyph); | |
326 else | |
327 size = DEFAULT_TOOLBAR_BLANK_SIZE; | |
328 } | |
329 else | |
330 { | |
331 struct window *w = XWINDOW (window); | |
332 Lisp_Object glyph = get_toolbar_button_glyph (w, tb); | |
333 | |
334 /* Unless, of course, the user has done something stupid like | |
335 change the glyph out from under us. Use a blank placeholder | |
336 in that case. */ | |
337 if (NILP (glyph)) | |
338 return XINT (f->toolbar_size[pos]); | |
339 | |
340 if (vert) | |
341 size = glyph_height (glyph, window); | |
342 else | |
343 size = glyph_width (glyph, window); | |
344 } | |
345 | |
346 if (!size) | |
347 { | |
348 /* If the glyph doesn't have a size we'll insert a blank | |
349 placeholder instead. */ | |
350 return XINT (f->toolbar_size[pos]); | |
351 } | |
352 | |
353 size += shadow_thickness * 2; | |
354 | |
355 return (size); | |
356 } | |
357 | |
358 #define COMMON_OUTPUT_BUTTONS_LOOP(left) \ | |
359 do { \ | |
360 while (!NILP (button)) \ | |
361 { \ | |
362 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); \ | |
363 int size, height, width; \ | |
364 \ | |
365 if (left && tb->pushright) \ | |
366 break; \ | |
367 \ | |
368 size = common_get_button_size (f, window, tb, vert, pos); \ | |
369 \ | |
370 if (vert) \ | |
371 { \ | |
372 width = bar_width; \ | |
373 if (y + size > max_pixpos) \ | |
374 height = max_pixpos - y; \ | |
375 else \ | |
376 height = size; \ | |
377 } \ | |
378 else \ | |
379 { \ | |
380 if (x + size > max_pixpos) \ | |
381 width = max_pixpos - x; \ | |
382 else \ | |
383 width = size; \ | |
384 height = bar_height; \ | |
385 } \ | |
386 \ | |
387 if (tb->x != x \ | |
388 || tb->y != y \ | |
389 || tb->width != width \ | |
390 || tb->height != height \ | |
391 || tb->dirty) \ | |
392 { \ | |
393 if (width && height) \ | |
394 { \ | |
395 tb->x = x; \ | |
396 tb->y = y; \ | |
397 tb->width = width; \ | |
398 tb->height = height; \ | |
399 tb->border_width = border_width; \ | |
400 tb->vertical = vert; \ | |
401 \ | |
402 if (tb->blank || NILP (tb->up_glyph)) \ | |
403 { \ | |
404 common_draw_blank_toolbar_button (f, tb); \ | |
405 } \ | |
406 else \ | |
407 common_output_toolbar_button (f, button); \ | |
408 } \ | |
409 } \ | |
410 \ | |
411 if (vert) \ | |
412 y += height; \ | |
413 else \ | |
414 x += width; \ | |
415 \ | |
416 if ((vert && y == max_pixpos) || (!vert && x == max_pixpos)) \ | |
417 button = Qnil; \ | |
418 else \ | |
419 button = tb->next; \ | |
420 } \ | |
421 } while (0) | |
422 | |
423 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ | |
424 do { \ | |
425 switch (pos) \ | |
426 { \ | |
427 case TOP_TOOLBAR: \ | |
428 (frame)->top_toolbar_was_visible = flag; \ | |
429 break; \ | |
430 case BOTTOM_TOOLBAR: \ | |
431 (frame)->bottom_toolbar_was_visible = flag; \ | |
432 break; \ | |
433 case LEFT_TOOLBAR: \ | |
434 (frame)->left_toolbar_was_visible = flag; \ | |
435 break; \ | |
436 case RIGHT_TOOLBAR: \ | |
437 (frame)->right_toolbar_was_visible = flag; \ | |
438 break; \ | |
439 default: \ | |
440 abort (); \ | |
441 } \ | |
442 } while (0) | |
443 | |
444 static void | |
445 common_output_toolbar (struct frame *f, enum toolbar_pos pos) | |
446 { | |
447 int x, y, bar_width, bar_height, vert; | |
448 int max_pixpos, right_size, right_start, blank_size; | |
449 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos); | |
450 Lisp_Object button, window; | |
451 face_index toolbar_findex; | |
452 | |
453 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1); | |
454 window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
455 toolbar_findex = get_builtin_face_cache_index (XWINDOW (window), Vtoolbar_face); | |
456 | |
457 /* Do the border */ | |
458 redisplay_clear_region (window, toolbar_findex, | |
459 x, y, | |
460 (vert ? bar_width : border_width), | |
461 (vert ? border_width : bar_height)); | |
462 redisplay_clear_region (window, toolbar_findex, | |
463 (vert ? x : x + bar_width - border_width), | |
464 (vert ? y + bar_height - border_width : y), | |
465 (vert ? bar_width : border_width), | |
466 (vert ? border_width : bar_height)); | |
467 | |
468 if (vert) | |
469 { | |
470 max_pixpos = y + bar_height - border_width; | |
471 y += border_width; | |
472 } | |
473 else | |
474 { | |
475 max_pixpos = x + bar_width - border_width; | |
476 x += border_width; | |
477 } | |
478 | |
479 button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
480 right_size = 0; | |
481 | |
482 /* First loop over all of the buttons to determine how much room we | |
483 need for left hand and right hand buttons. This loop will also | |
484 make sure that all instances are instantiated so when we actually | |
485 output them they will come up immediately. */ | |
486 while (!NILP (button)) | |
487 { | |
488 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
489 int size = common_get_button_size (f, window, tb, vert, pos); | |
490 | |
491 if (tb->pushright) | |
492 right_size += size; | |
493 | |
494 button = tb->next; | |
495 } | |
496 | |
497 button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
498 | |
499 /* Loop over the left buttons, updating and outputting them. */ | |
500 COMMON_OUTPUT_BUTTONS_LOOP (1); | |
501 | |
502 /* Now determine where the right buttons start. */ | |
503 right_start = max_pixpos - right_size; | |
504 if (right_start < (vert ? y : x)) | |
505 right_start = (vert ? y : x); | |
506 | |
507 /* Output the blank which goes from the end of the left buttons to | |
508 the start of the right. */ | |
509 blank_size = right_start - (vert ? y : x); | |
510 if (blank_size) | |
511 { | |
512 int height, width; | |
513 | |
514 if (vert) | |
515 { | |
516 width = bar_width; | |
517 height = blank_size; | |
518 } | |
519 else | |
520 { | |
521 width = blank_size; | |
522 height = bar_height; | |
523 } | |
524 | |
525 /* | |
526 * Use a 3D pushright separator only if there isn't a toolbar | |
527 * border. A flat separator meshes with the border and looks | |
528 * better. | |
529 */ | |
530 if (1) | |
531 { | |
532 struct toolbar_button tb; | |
533 | |
534 tb.x = x; | |
535 tb.y = y; | |
536 tb.width = width; | |
537 tb.height = height; | |
538 tb.border_width = border_width; | |
539 tb.vertical = vert; | |
540 tb.enabled = 1; | |
541 tb.up_glyph = border_width ? Qt : Qnil; | |
542 | |
543 __prepare_button_area (f, &tb); | |
544 } | |
545 | |
546 if (vert) | |
547 y += height; | |
548 else | |
549 x += width; | |
550 } | |
551 | |
552 /* Loop over the right buttons, updating and outputting them. */ | |
553 COMMON_OUTPUT_BUTTONS_LOOP (0); | |
554 | |
555 if (!vert) | |
556 { | |
557 Lisp_Object frame; | |
558 | |
559 XSETFRAME (frame, f); | |
560 redisplay_clear_region (frame, | |
561 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1, | |
562 bar_height); | |
563 } | |
564 | |
565 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1); | |
566 __INTERNAL_FLUSH (XDEVICE (f->device)); | |
567 } | |
568 | |
569 static void | |
570 common_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change) | |
571 { | |
572 Lisp_Object frame; | |
573 int x, y, width, height, vert; | |
574 | |
575 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1); | |
576 XSETFRAME (frame, f); | |
577 | |
578 /* The thickness_change parameter is used by the toolbar resize routines | |
579 to clear any excess toolbar if the size shrinks. */ | |
580 if (thickness_change < 0) | |
581 { | |
582 if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR) | |
583 { | |
584 x = x + width + thickness_change; | |
585 width = -thickness_change; | |
586 } | |
587 else | |
588 { | |
589 y = y + height + thickness_change; | |
590 height = -thickness_change; | |
591 } | |
592 } | |
593 | |
594 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0); | |
595 | |
596 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height); | |
597 | |
598 __INTERNAL_FLUSH (XDEVICE (f->device)); | |
599 } | |
600 | |
601 void | |
602 common_output_frame_toolbars (struct frame *f) | |
603 { | |
604 __INTERNAL_APPROPRIATENESS_CHECK(f); | |
605 | |
606 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) | |
607 common_output_toolbar (f, TOP_TOOLBAR); | |
608 else if (f->top_toolbar_was_visible) | |
609 common_clear_toolbar (f, TOP_TOOLBAR, 0); | |
610 | |
611 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) | |
612 common_output_toolbar (f, BOTTOM_TOOLBAR); | |
613 else if (f->bottom_toolbar_was_visible) | |
614 common_clear_toolbar (f, BOTTOM_TOOLBAR, 0); | |
615 | |
616 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) | |
617 common_output_toolbar (f, LEFT_TOOLBAR); | |
618 else if (f->left_toolbar_was_visible) | |
619 common_clear_toolbar (f, LEFT_TOOLBAR, 0); | |
620 | |
621 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) | |
622 common_output_toolbar (f, RIGHT_TOOLBAR); | |
623 else if (f->right_toolbar_was_visible) | |
624 common_clear_toolbar (f, RIGHT_TOOLBAR, 0); | |
625 } | |
626 | |
627 static void | |
628 common_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y, | |
629 int width, int height) | |
630 { | |
631 int bar_x, bar_y, bar_width, bar_height, vert; | |
632 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos); | |
633 | |
634 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height, | |
635 &vert, 1); | |
636 | |
637 if (((y + height) < bar_y) || (y > (bar_y + bar_height))) | |
638 return; | |
639 if (((x + width) < bar_x) || (x > (bar_x + bar_width))) | |
640 return; | |
641 | |
642 while (!NILP (button)) | |
643 { | |
644 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); | |
645 | |
646 if (vert) | |
647 { | |
648 if (((tb->y + tb->height) > y) && (tb->y < (y + height))) | |
649 tb->dirty = 1; | |
650 | |
651 /* If this is true we have gone past the exposed region. */ | |
652 if (tb->y > (y + height)) | |
653 break; | |
654 } | |
655 else | |
656 { | |
657 if (((tb->x + tb->width) > x) && (tb->x < (x + width))) | |
658 tb->dirty = 1; | |
659 | |
660 /* If this is true we have gone past the exposed region. */ | |
661 if (tb->x > (x + width)) | |
662 break; | |
663 } | |
664 | |
665 button = tb->next; | |
666 } | |
667 | |
668 /* Even if none of the buttons is in the area, the blank region at | |
669 the very least must be because the first thing we did is verify | |
670 that some portion of the toolbar is in the exposed region. */ | |
671 common_output_toolbar (f, pos); | |
672 } | |
673 | |
674 void | |
675 common_redraw_exposed_toolbars (struct frame *f, int x, int y, int width, | |
676 int height) | |
677 { | |
678 __INTERNAL_APPROPRIATENESS_CHECK(f); | |
679 | |
680 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) | |
681 common_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height); | |
682 | |
683 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) | |
684 common_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height); | |
685 | |
686 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) | |
687 common_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height); | |
688 | |
689 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) | |
690 common_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height); | |
691 } | |
692 | |
693 void | |
694 common_redraw_frame_toolbars (struct frame *f) | |
695 { | |
696 /* There are certain startup paths that lead to update_EmacsFrame in | |
697 faces.c being called before a new frame is fully initialized. In | |
698 particular before we have actually mapped it. That routine can | |
699 call this one. So, we need to make sure that the frame is | |
700 actually ready before we try and draw all over it. */ | |
701 | |
702 if (__INTERNAL_MAPPED_P(f)) | |
703 common_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f), | |
704 FRAME_PIXHEIGHT (f)); | |
705 } | |
706 |