comparison src/toolbar.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 /* Generic toolbar implementation.
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 /* Original implementation by Chuck Thompson for 19.12.
27 Default-toolbar-position and specifier-related stuff by Ben Wing. */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "buffer.h"
33 #include "frame.h"
34 #include "device.h"
35 #include "glyphs.h"
36 #include "redisplay.h"
37 #include "toolbar.h"
38 #include "window.h"
39
40 Lisp_Object Vtoolbar[4];
41 Lisp_Object Vtoolbar_size[4];
42 Lisp_Object Vtoolbar_visible_p[4];
43 Lisp_Object Vtoolbar_border_width[4];
44
45 Lisp_Object Vdefault_toolbar, Vdefault_toolbar_visible_p;
46 Lisp_Object Vdefault_toolbar_width, Vdefault_toolbar_height;
47 Lisp_Object Vdefault_toolbar_border_width;
48
49 Lisp_Object Vdefault_toolbar_position;
50 Lisp_Object Vtoolbar_buttons_captioned_p;
51
52 Lisp_Object Qtoolbar_buttonp;
53 Lisp_Object Q2D, Q3D, Q2d, Q3d;
54 Lisp_Object Q_size;
55
56 Lisp_Object Qinit_toolbar_from_resources;
57
58
59 static Lisp_Object
60 mark_toolbar_button (Lisp_Object obj)
61 {
62 struct toolbar_button *data = XTOOLBAR_BUTTON (obj);
63 mark_object (data->next);
64 mark_object (data->frame);
65 mark_object (data->up_glyph);
66 mark_object (data->down_glyph);
67 mark_object (data->disabled_glyph);
68 mark_object (data->cap_up_glyph);
69 mark_object (data->cap_down_glyph);
70 mark_object (data->cap_disabled_glyph);
71 mark_object (data->callback);
72 mark_object (data->enabled_p);
73 return data->help_string;
74 }
75
76 static void
77 print_toolbar_button (Lisp_Object obj, Lisp_Object printcharfun,
78 int escapeflag)
79 {
80 struct toolbar_button *tb = XTOOLBAR_BUTTON (obj);
81 char buf[100];
82
83 if (print_readably)
84 error ("printing unreadable object #<toolbar-button 0x%x>",
85 tb->header.uid);
86
87 sprintf (buf, "#<toolbar-button 0x%x>", tb->header.uid);
88 write_c_string (buf, printcharfun);
89 }
90
91 DEFINE_LRECORD_IMPLEMENTATION ("toolbar-button", toolbar_button,
92 mark_toolbar_button, print_toolbar_button,
93 0, 0, 0, 0,
94 struct toolbar_button);
95
96 DEFUN ("toolbar-button-p", Ftoolbar_button_p, 1, 1, 0, /*
97 Return non-nil if OBJECT is a toolbar button.
98 */
99 (object))
100 {
101 return TOOLBAR_BUTTONP (object) ? Qt : Qnil;
102 }
103
104 /* Only query functions are provided for toolbar buttons. They are
105 generated and updated from a toolbar description list. Any
106 directly made changes would be wiped out the first time the toolbar
107 was marked as dirty and was regenerated. The exception to this is
108 set-toolbar-button-down-flag. Having this allows us to control the
109 toolbar from elisp. Since we only trigger the button callbacks on
110 up-mouse events and we reset the flag first, there shouldn't be any
111 way for this to get us in trouble (like if someone decides to
112 change the toolbar from a toolbar callback). */
113
114 DEFUN ("toolbar-button-callback", Ftoolbar_button_callback, 1, 1, 0, /*
115 Return the callback function associated with the toolbar BUTTON.
116 */
117 (button))
118 {
119 CHECK_TOOLBAR_BUTTON (button);
120
121 return XTOOLBAR_BUTTON (button)->callback;
122 }
123
124 DEFUN ("toolbar-button-help-string", Ftoolbar_button_help_string, 1, 1, 0, /*
125 Return the help string function associated with the toolbar BUTTON.
126 */
127 (button))
128 {
129 CHECK_TOOLBAR_BUTTON (button);
130
131 return XTOOLBAR_BUTTON (button)->help_string;
132 }
133
134 DEFUN ("toolbar-button-enabled-p", Ftoolbar_button_enabled_p, 1, 1, 0, /*
135 Return t if BUTTON is active.
136 */
137 (button))
138 {
139 CHECK_TOOLBAR_BUTTON (button);
140
141 return XTOOLBAR_BUTTON (button)->enabled ? Qt : Qnil;
142 }
143
144 DEFUN ("set-toolbar-button-down-flag", Fset_toolbar_button_down_flag, 2, 2, 0, /*
145 Don't touch.
146 */
147 (button, flag))
148 {
149 struct toolbar_button *tb;
150 char old_flag;
151
152 CHECK_TOOLBAR_BUTTON (button);
153 tb = XTOOLBAR_BUTTON (button);
154 old_flag = tb->down;
155
156 /* If the button is ignored, don't do anything. */
157 if (!tb->enabled)
158 return Qnil;
159
160 /* If flag is nil, unset the down flag, otherwise set it to true.
161 This also triggers an immediate redraw of the button if the flag
162 does change. */
163
164 if (NILP (flag))
165 tb->down = 0;
166 else
167 tb->down = 1;
168
169 if (tb->down != old_flag)
170 {
171 struct frame *f = XFRAME (tb->frame);
172 struct device *d;
173
174 if (DEVICEP (f->device))
175 {
176 d = XDEVICE (f->device);
177
178 if (DEVICE_LIVE_P (XDEVICE (f->device)))
179 {
180 tb->dirty = 1;
181 MAYBE_DEVMETH (d, output_toolbar_button, (f, button));
182 }
183 }
184 }
185
186 return Qnil;
187 }
188
189 Lisp_Object
190 get_toolbar_button_glyph (struct window *w, struct toolbar_button *tb)
191 {
192 Lisp_Object glyph = Qnil;
193
194 /* The selected glyph logic:
195
196 UP: up
197 DOWN: down -> up
198 DISABLED: disabled -> up
199 CAP-UP: cap-up -> up
200 CAP-DOWN: cap-down -> cap-up -> down -> up
201 CAP-DISABLED: cap-disabled -> cap-up -> disabled -> up
202 */
203
204 if (!NILP (w->toolbar_buttons_captioned_p))
205 {
206 if (tb->enabled && tb->down)
207 glyph = tb->cap_down_glyph;
208 else if (!tb->enabled)
209 glyph = tb->cap_disabled_glyph;
210
211 if (NILP (glyph))
212 glyph = tb->cap_up_glyph;
213 }
214
215 if (NILP (glyph))
216 {
217 if (tb->enabled && tb->down)
218 glyph = tb->down_glyph;
219 else if (!tb->enabled)
220 glyph = tb->disabled_glyph;
221 }
222
223 /* The non-captioned up button is the ultimate fallback. It is
224 the only one we guarantee exists. */
225 if (NILP (glyph))
226 glyph = tb->up_glyph;
227
228 return glyph;
229 }
230
231
232 static enum toolbar_pos
233 decode_toolbar_position (Lisp_Object position)
234 {
235 if (EQ (position, Qtop)) return TOP_TOOLBAR;
236 if (EQ (position, Qbottom)) return BOTTOM_TOOLBAR;
237 if (EQ (position, Qleft)) return LEFT_TOOLBAR;
238 if (EQ (position, Qright)) return RIGHT_TOOLBAR;
239 signal_simple_error ("Invalid toolbar position", position);
240
241 return TOP_TOOLBAR; /* not reached */
242 }
243
244 DEFUN ("set-default-toolbar-position", Fset_default_toolbar_position, 1, 1, 0, /*
245 Set the position that the `default-toolbar' will be displayed at.
246 Valid positions are 'top, 'bottom, 'left and 'right.
247 See `default-toolbar-position'.
248 */
249 (position))
250 {
251 enum toolbar_pos cur = decode_toolbar_position (Vdefault_toolbar_position);
252 enum toolbar_pos new = decode_toolbar_position (position);
253
254 if (cur != new)
255 {
256 /* The following calls will automatically cause the dirty
257 flags to be set; we delay frame size changes to avoid
258 lots of frame flickering. */
259 /* #### I think this should be GC protected. -sb */
260 hold_frame_size_changes ();
261 set_specifier_fallback (Vtoolbar[cur], list1 (Fcons (Qnil, Qnil)));
262 set_specifier_fallback (Vtoolbar[new], Vdefault_toolbar);
263 set_specifier_fallback (Vtoolbar_size[cur], list1 (Fcons (Qnil, Qzero)));
264 set_specifier_fallback (Vtoolbar_size[new],
265 new == TOP_TOOLBAR || new == BOTTOM_TOOLBAR
266 ? Vdefault_toolbar_height
267 : Vdefault_toolbar_width);
268 set_specifier_fallback (Vtoolbar_border_width[cur],
269 list1 (Fcons (Qnil, Qzero)));
270 set_specifier_fallback (Vtoolbar_border_width[new],
271 Vdefault_toolbar_border_width);
272 set_specifier_fallback (Vtoolbar_visible_p[cur],
273 list1 (Fcons (Qnil, Qt)));
274 set_specifier_fallback (Vtoolbar_visible_p[new],
275 Vdefault_toolbar_visible_p);
276 Vdefault_toolbar_position = position;
277 unhold_frame_size_changes ();
278 }
279
280 return position;
281 }
282
283 DEFUN ("default-toolbar-position", Fdefault_toolbar_position, 0, 0, 0, /*
284 Return the position that the `default-toolbar' will be displayed at.
285 The `default-toolbar' will only be displayed here if the corresponding
286 position-specific toolbar specifier does not provide a value.
287 */
288 ())
289 {
290 return Vdefault_toolbar_position;
291 }
292
293
294 static Lisp_Object
295 update_toolbar_button (struct frame *f, struct toolbar_button *tb,
296 Lisp_Object desc, int pushright)
297 {
298 Lisp_Object *elt, glyphs, retval, buffer;
299 struct gcpro gcpro1, gcpro2;
300
301 elt = XVECTOR_DATA (desc);
302 buffer = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f))->buffer;
303
304 if (!tb)
305 {
306 tb = alloc_lcrecord_type (struct toolbar_button, &lrecord_toolbar_button);
307 tb->next = Qnil;
308 XSETFRAME (tb->frame, f);
309 tb->up_glyph = Qnil;
310 tb->down_glyph = Qnil;
311 tb->disabled_glyph = Qnil;
312 tb->cap_up_glyph = Qnil;
313 tb->cap_down_glyph = Qnil;
314 tb->cap_disabled_glyph = Qnil;
315 tb->callback = Qnil;
316 tb->enabled_p = Qnil;
317 tb->help_string = Qnil;
318
319 tb->enabled = 0;
320 tb->down = 0;
321 tb->pushright = pushright;
322 tb->blank = 0;
323 tb->x = tb->y = tb->width = tb->height = -1;
324 tb->dirty = 1;
325 }
326 XSETTOOLBAR_BUTTON (retval, tb);
327
328 /* Let's make sure nothing gets mucked up by the potential call to
329 eval farther down. */
330 GCPRO2 (retval, desc);
331
332 glyphs = (CONSP (elt[0]) ? elt[0] : symbol_value_in_buffer (elt[0], buffer));
333
334 /* If this is true we have a blank, otherwise it is an actual
335 button. */
336 if (KEYWORDP (glyphs))
337 {
338 int pos;
339 int style_seen = 0;
340 int size_seen = 0;
341 int len = XVECTOR_LENGTH (desc);
342
343 if (!tb->blank)
344 {
345 tb->blank = 1;
346 tb->dirty = 1;
347 }
348
349 for (pos = 0; pos < len; pos += 2)
350 {
351 Lisp_Object key = elt[pos];
352 Lisp_Object val = elt[pos + 1];
353
354 if (EQ (key, Q_style))
355 {
356 style_seen = 1;
357
358 if (EQ (val, Q2D) || EQ (val, Q2d))
359 {
360 if (!EQ (Qnil, tb->up_glyph) || !EQ (Qt, tb->disabled_glyph))
361 {
362 tb->up_glyph = Qnil;
363 tb->disabled_glyph = Qt;
364 tb->dirty = 1;
365 }
366 }
367 else if (EQ (val, Q3D) || (EQ (val, Q3d)))
368 {
369 if (!EQ (Qt, tb->up_glyph) || !EQ (Qnil, tb->disabled_glyph))
370 {
371 tb->up_glyph = Qt;
372 tb->disabled_glyph = Qnil;
373 tb->dirty = 1;
374 }
375 }
376 }
377 else if (EQ (key, Q_size))
378 {
379 size_seen = 1;
380
381 if (!EQ (val, tb->down_glyph))
382 {
383 tb->down_glyph = val;
384 tb->dirty = 1;
385 }
386 }
387 }
388
389 if (!style_seen)
390 {
391 /* The default style is 3D. */
392 if (!EQ (Qt, tb->up_glyph) || !EQ (Qnil, tb->disabled_glyph))
393 {
394 tb->up_glyph = Qt;
395 tb->disabled_glyph = Qnil;
396 tb->dirty = 1;
397 }
398 }
399
400 if (!size_seen)
401 {
402 /* The default width is set to nil. The device specific
403 code will fill it in at its discretion. */
404 if (!NILP (tb->down_glyph))
405 {
406 tb->down_glyph = Qnil;
407 tb->dirty = 1;
408 }
409 }
410
411 /* The rest of these fields are not used by blanks. We make
412 sure they are nulled out in case this button object formerly
413 represented a real button. */
414 if (!NILP (tb->callback)
415 || !NILP (tb->enabled_p)
416 || !NILP (tb->help_string))
417 {
418 tb->cap_up_glyph = Qnil;
419 tb->cap_down_glyph = Qnil;
420 tb->cap_disabled_glyph = Qnil;
421 tb->callback = Qnil;
422 tb->enabled_p = Qnil;
423 tb->help_string = Qnil;
424 tb->dirty = 1;
425 }
426 }
427 else
428 {
429 if (tb->blank)
430 {
431 tb->blank = 0;
432 tb->dirty = 1;
433 }
434
435 /* We know that we at least have an up_glyph. Well, no, we
436 don't. The user may have changed the button glyph on us. */
437 if (CONSP (glyphs))
438 {
439 if (!EQ (XCAR (glyphs), tb->up_glyph))
440 {
441 tb->up_glyph = XCAR (glyphs);
442 tb->dirty = 1;
443 }
444 glyphs = XCDR (glyphs);
445 }
446 else
447 tb->up_glyph = Qnil;
448
449 /* We might have a down_glyph. */
450 if (CONSP (glyphs))
451 {
452 if (!EQ (XCAR (glyphs), tb->down_glyph))
453 {
454 tb->down_glyph = XCAR (glyphs);
455 tb->dirty = 1;
456 }
457 glyphs = XCDR (glyphs);
458 }
459 else
460 tb->down_glyph = Qnil;
461
462 /* We might have a disabled_glyph. */
463 if (CONSP (glyphs))
464 {
465 if (!EQ (XCAR (glyphs), tb->disabled_glyph))
466 {
467 tb->disabled_glyph = XCAR (glyphs);
468 tb->dirty = 1;
469 }
470 glyphs = XCDR (glyphs);
471 }
472 else
473 tb->disabled_glyph = Qnil;
474
475 /* We might have a cap_up_glyph. */
476 if (CONSP (glyphs))
477 {
478 if (!EQ (XCAR (glyphs), tb->cap_up_glyph))
479 {
480 tb->cap_up_glyph = XCAR (glyphs);
481 tb->dirty = 1;
482 }
483 glyphs = XCDR (glyphs);
484 }
485 else
486 tb->cap_up_glyph = Qnil;
487
488 /* We might have a cap_down_glyph. */
489 if (CONSP (glyphs))
490 {
491 if (!EQ (XCAR (glyphs), tb->cap_down_glyph))
492 {
493 tb->cap_down_glyph = XCAR (glyphs);
494 tb->dirty = 1;
495 }
496 glyphs = XCDR (glyphs);
497 }
498 else
499 tb->cap_down_glyph = Qnil;
500
501 /* We might have a cap_disabled_glyph. */
502 if (CONSP (glyphs))
503 {
504 if (!EQ (XCAR (glyphs), tb->cap_disabled_glyph))
505 {
506 tb->cap_disabled_glyph = XCAR (glyphs);
507 tb->dirty = 1;
508 }
509 }
510 else
511 tb->cap_disabled_glyph = Qnil;
512
513 /* Update the callback. */
514 if (!EQ (tb->callback, elt[1]))
515 {
516 tb->callback = elt[1];
517 /* This does not have an impact on the display properties of the
518 button so we do not mark it as dirty if it has changed. */
519 }
520
521 /* Update the enabled field. */
522 if (!EQ (tb->enabled_p, elt[2]))
523 {
524 tb->enabled_p = elt[2];
525 tb->dirty = 1;
526 }
527
528 /* We always do the following because if the enabled status is
529 determined by a function its decision may change without us being
530 able to detect it. */
531 {
532 int old_enabled = tb->enabled;
533
534 if (NILP (tb->enabled_p))
535 tb->enabled = 0;
536 else if (EQ (tb->enabled_p, Qt))
537 tb->enabled = 1;
538 else
539 {
540 if (NILP (tb->enabled_p) || EQ (tb->enabled_p, Qt))
541 /* short-circuit the common case for speed */
542 tb->enabled = !NILP (tb->enabled_p);
543 else
544 {
545 Lisp_Object result =
546 eval_in_buffer_trapping_errors
547 ("Error in toolbar enabled-p form",
548 XBUFFER
549 (WINDOW_BUFFER
550 (XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)))),
551 tb->enabled_p);
552 if (UNBOUNDP (result))
553 /* #### if there was an error in the enabled-p
554 form, should we pretend like it's enabled
555 or disabled? */
556 tb->enabled = 0;
557 else
558 tb->enabled = !NILP (result);
559 }
560 }
561
562 if (old_enabled != tb->enabled)
563 tb->dirty = 1;
564 }
565
566 /* Update the help echo string. */
567 if (!EQ (tb->help_string, elt[3]))
568 {
569 tb->help_string = elt[3];
570 /* This does not have an impact on the display properties of the
571 button so we do not mark it as dirty if it has changed. */
572 }
573 }
574
575 /* If this flag changes, the position is changing for sure unless
576 some very unlikely geometry occurs. */
577 if (tb->pushright != pushright)
578 {
579 tb->pushright = pushright;
580 tb->dirty = 1;
581 }
582
583 /* The position and size fields are only manipulated in the
584 device-dependent code. */
585 UNGCPRO;
586 return retval;
587 }
588
589 void
590 mark_frame_toolbar_buttons_dirty (struct frame *f, enum toolbar_pos pos)
591 {
592 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos);
593
594 while (!NILP (button))
595 {
596 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
597 tb->dirty = 1;
598 button = tb->next;
599 }
600 return;
601 }
602
603 static Lisp_Object
604 compute_frame_toolbar_buttons (struct frame *f, enum toolbar_pos pos,
605 Lisp_Object toolbar)
606 {
607 Lisp_Object buttons, prev_button, first_button;
608 Lisp_Object orig_toolbar = toolbar;
609 int pushright_seen = 0;
610 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
611
612 first_button = FRAME_TOOLBAR_BUTTONS (f, pos);
613 buttons = prev_button = first_button;
614
615 /* Yes, we're being paranoid. */
616 GCPRO5 (toolbar, buttons, prev_button, first_button, orig_toolbar);
617
618 if (NILP (toolbar))
619 {
620 /* The output mechanisms will take care of clearing the former
621 toolbar. */
622 UNGCPRO;
623 return Qnil;
624 }
625
626 if (!CONSP (toolbar))
627 signal_simple_error ("toolbar description must be a list", toolbar);
628
629 /* First synchronize any existing buttons. */
630 while (!NILP (toolbar) && !NILP (buttons))
631 {
632 struct toolbar_button *tb;
633
634 if (NILP (XCAR (toolbar)))
635 {
636 if (pushright_seen)
637 signal_simple_error
638 ("more than one partition (nil) in toolbar description",
639 orig_toolbar);
640 else
641 pushright_seen = 1;
642 }
643 else
644 {
645 tb = XTOOLBAR_BUTTON (buttons);
646 update_toolbar_button (f, tb, XCAR (toolbar), pushright_seen);
647 prev_button = buttons;
648 buttons = tb->next;
649 }
650
651 toolbar = XCDR (toolbar);
652 }
653
654 /* If we hit the end of the toolbar, then clean up any excess
655 buttons and return. */
656 if (NILP (toolbar))
657 {
658 if (!NILP (buttons))
659 {
660 /* If this is the case the only thing we saw was a
661 pushright marker. */
662 if (EQ (buttons, first_button))
663 {
664 UNGCPRO;
665 return Qnil;
666 }
667 else
668 XTOOLBAR_BUTTON (prev_button)->next = Qnil;
669 }
670 UNGCPRO;
671 return first_button;
672 }
673
674 /* At this point there are more buttons on the toolbar than we
675 actually have in existence. */
676 while (!NILP (toolbar))
677 {
678 Lisp_Object new_button;
679
680 if (NILP (XCAR (toolbar)))
681 {
682 if (pushright_seen)
683 signal_simple_error
684 ("more than one partition (nil) in toolbar description",
685 orig_toolbar);
686 else
687 pushright_seen = 1;
688 }
689 else
690 {
691 new_button = update_toolbar_button (f, NULL, XCAR (toolbar),
692 pushright_seen);
693
694 if (NILP (first_button))
695 {
696 first_button = prev_button = new_button;
697 }
698 else
699 {
700 XTOOLBAR_BUTTON (prev_button)->next = new_button;
701 prev_button = new_button;
702 }
703 }
704
705 toolbar = XCDR (toolbar);
706 }
707
708 UNGCPRO;
709 return first_button;
710 }
711
712 static void
713 set_frame_toolbar (struct frame *f, enum toolbar_pos pos)
714 {
715 struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
716 Lisp_Object toolbar = w->toolbar[pos];
717 f->toolbar_buttons[pos] = (FRAME_REAL_TOOLBAR_VISIBLE (f, pos)
718 ? compute_frame_toolbar_buttons (f, pos, toolbar)
719 : Qnil);
720 }
721
722 static void
723 compute_frame_toolbars_data (struct frame *f)
724 {
725 set_frame_toolbar (f, TOP_TOOLBAR);
726 set_frame_toolbar (f, BOTTOM_TOOLBAR);
727 set_frame_toolbar (f, LEFT_TOOLBAR);
728 set_frame_toolbar (f, RIGHT_TOOLBAR);
729 }
730
731 void
732 update_frame_toolbars (struct frame *f)
733 {
734 struct device *d = XDEVICE (f->device);
735
736 if (DEVICE_SUPPORTS_TOOLBARS_P (d)
737 && (f->toolbar_changed || f->frame_changed || f->clear))
738 {
739 int pos;
740
741 /* We're not officially "in redisplay", so we still have a
742 chance to re-layout toolbars and windows. This is done here,
743 because toolbar is the only thing which currently might
744 necessitate this layout, as it is outside any windows. We
745 take care not to change size if toolbar geometry is really
746 unchanged, as it will hose windows whose pixsizes are not
747 multiple of character sizes. */
748
749 for (pos = 0; pos < 4; pos++)
750 if (FRAME_REAL_TOOLBAR_SIZE (f, pos)
751 != FRAME_CURRENT_TOOLBAR_SIZE (f, pos))
752 {
753 int width, height;
754 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
755 &width, &height);
756 change_frame_size (f, height, width, 0);
757 break;
758 }
759
760 for (pos = 0; pos < 4; pos++)
761 f->current_toolbar_size[pos] = FRAME_REAL_TOOLBAR_SIZE (f, pos);
762
763 /* Removed the check for the minibuffer here. We handle this
764 more correctly now by consistently using
765 FRAME_LAST_NONMINIBUF_WINDOW instead of FRAME_SELECTED_WINDOW
766 throughout the toolbar code. */
767 compute_frame_toolbars_data (f);
768
769 DEVMETH (d, output_frame_toolbars, (f));
770 }
771
772 f->toolbar_changed = 0;
773 }
774
775 void
776 init_frame_toolbars (struct frame *f)
777 {
778 struct device *d = XDEVICE (f->device);
779
780 if (DEVICE_SUPPORTS_TOOLBARS_P (d))
781 {
782 Lisp_Object frame;
783 int pos;
784
785 compute_frame_toolbars_data (f);
786 XSETFRAME (frame, f);
787 call_critical_lisp_code (XDEVICE (FRAME_DEVICE (f)),
788 Qinit_toolbar_from_resources,
789 frame);
790 MAYBE_DEVMETH (d, initialize_frame_toolbars, (f));
791
792 /* We are here as far in frame creation so cached specifiers are
793 already recomputed, and possibly modified by resource
794 initialization. Remember current toolbar geometry so next
795 redisplay will not needlessly relayout toolbars. */
796 for (pos = 0; pos < 4; pos++)
797 f->current_toolbar_size[pos] = FRAME_REAL_TOOLBAR_SIZE (f, pos);
798 }
799 }
800
801 void
802 init_device_toolbars (struct device *d)
803 {
804 Lisp_Object device;
805
806 XSETDEVICE (device, d);
807 if (DEVICE_SUPPORTS_TOOLBARS_P (d))
808 call_critical_lisp_code (d,
809 Qinit_toolbar_from_resources,
810 device);
811 }
812
813 void
814 init_global_toolbars (struct device *d)
815 {
816 if (DEVICE_SUPPORTS_TOOLBARS_P (d))
817 call_critical_lisp_code (d,
818 Qinit_toolbar_from_resources,
819 Qglobal);
820 }
821
822 void
823 free_frame_toolbars (struct frame *f)
824 {
825 /* If we had directly allocated any memory for the toolbars instead
826 of using all Lisp_Objects this is where we would now free it. */
827
828 MAYBE_FRAMEMETH (f, free_frame_toolbars, (f));
829 }
830
831 void
832 get_toolbar_coords (struct frame *f, enum toolbar_pos pos, int *x, int *y,
833 int *width, int *height, int *vert, int for_layout)
834 {
835 int visible_top_toolbar_height, visible_bottom_toolbar_height;
836 int adjust = (for_layout ? 1 : 0);
837
838 /* The top and bottom toolbars take precedence over the left and
839 right. */
840 visible_top_toolbar_height = (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)
841 ? FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) +
842 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f)
843 : 0);
844 visible_bottom_toolbar_height = (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)
845 ? FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) +
846 2 *
847 FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)
848 : 0);
849
850 /* We adjust the width and height by one to give us a narrow border
851 at the outside edges. However, when we are simply determining
852 toolbar location we don't want to do that. */
853
854 switch (pos)
855 {
856 case TOP_TOOLBAR:
857 *x = 1;
858 *y = 0; /* #### should be 1 if no menubar */
859 *width = FRAME_PIXWIDTH (f) - 2;
860 *height = FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) +
861 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f) - adjust;
862 *vert = 0;
863 break;
864 case BOTTOM_TOOLBAR:
865 *x = 1;
866 *y = FRAME_PIXHEIGHT (f) - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -
867 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f);
868 *width = FRAME_PIXWIDTH (f) - 2;
869 *height = FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) +
870 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f) - adjust;
871 *vert = 0;
872 break;
873 case LEFT_TOOLBAR:
874 *x = 1;
875 *y = visible_top_toolbar_height;
876 *width = FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) +
877 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f) - adjust;
878 *height = (FRAME_PIXHEIGHT (f) - visible_top_toolbar_height -
879 visible_bottom_toolbar_height - 1);
880 *vert = 1;
881 break;
882 case RIGHT_TOOLBAR:
883 *x = FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -
884 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f);
885 *y = visible_top_toolbar_height;
886 *width = FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) +
887 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f) - adjust;
888 *height = (FRAME_PIXHEIGHT (f) - visible_top_toolbar_height -
889 visible_bottom_toolbar_height);
890 *vert = 1;
891 break;
892 default:
893 abort ();
894 }
895 }
896
897 #define CHECK_TOOLBAR(pos) do { \
898 if (FRAME_REAL_##pos##_VISIBLE (f)) \
899 { \
900 int x, y, width, height, vert; \
901 \
902 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 0); \
903 if ((x_coord >= x) && (x_coord < (x + width))) \
904 { \
905 if ((y_coord >= y) && (y_coord < (y + height))) \
906 return FRAME_TOOLBAR_BUTTONS (f, pos); \
907 } \
908 } \
909 } while (0)
910
911 static Lisp_Object
912 toolbar_buttons_at_pixpos (struct frame *f, int x_coord, int y_coord)
913 {
914 CHECK_TOOLBAR (TOP_TOOLBAR);
915 CHECK_TOOLBAR (BOTTOM_TOOLBAR);
916 CHECK_TOOLBAR (LEFT_TOOLBAR);
917 CHECK_TOOLBAR (RIGHT_TOOLBAR);
918
919 return Qnil;
920 }
921 #undef CHECK_TOOLBAR
922
923 /* The device dependent code actually does the work of positioning the
924 buttons, but we are free to access that information at this
925 level. */
926 Lisp_Object
927 toolbar_button_at_pixpos (struct frame *f, int x_coord, int y_coord)
928 {
929 Lisp_Object buttons = toolbar_buttons_at_pixpos (f, x_coord, y_coord);
930
931 while (!NILP (buttons))
932 {
933 struct toolbar_button *tb = XTOOLBAR_BUTTON (buttons);
934
935 if ((x_coord >= tb->x) && (x_coord < (tb->x + tb->width)))
936 {
937 if ((y_coord >= tb->y) && (y_coord < (tb->y + tb->height)))
938 {
939 /* If we are over a blank, return nil. */
940 if (tb->blank)
941 return Qnil;
942 else
943 return buttons;
944 }
945 }
946
947 buttons = tb->next;
948 }
949
950 /* We are not over a toolbar or we are over a blank in the toolbar. */
951 return Qnil;
952 }
953
954
955 /************************************************************************/
956 /* Toolbar specifier type */
957 /************************************************************************/
958
959 DEFINE_SPECIFIER_TYPE (toolbar);
960
961 #define CTB_ERROR(msg) do { \
962 maybe_signal_simple_error (msg, button, Qtoolbar, errb); \
963 RETURN_SANS_WARNINGS Qnil; \
964 } while (0)
965
966 /* Returns Q_style if key was :style, Qt if ok otherwise, Qnil if error. */
967 static Lisp_Object
968 check_toolbar_button_keywords (Lisp_Object button, Lisp_Object key,
969 Lisp_Object val, Error_behavior errb)
970 {
971 if (!KEYWORDP (key))
972 {
973 maybe_signal_simple_error_2 ("Not a keyword", key, button, Qtoolbar,
974 errb);
975 return Qnil;
976 }
977
978 if (EQ (key, Q_style))
979 {
980 if (!EQ (val, Q2D)
981 && !EQ (val, Q3D)
982 && !EQ (val, Q2d)
983 && !EQ (val, Q3d))
984 CTB_ERROR ("Unrecognized toolbar blank style");
985
986 return Q_style;
987 }
988 else if (EQ (key, Q_size))
989 {
990 if (!NATNUMP (val))
991 CTB_ERROR ("invalid toolbar blank size");
992 }
993 else
994 {
995 CTB_ERROR ("invalid toolbar blank keyword");
996 }
997
998 return Qt;
999 }
1000
1001 /* toolbar button spec is [pixmap-pair function enabled-p help]
1002 or [:style 2d-or-3d :size width-or-height] */
1003
1004 DEFUN ("check-toolbar-button-syntax", Fcheck_toolbar_button_syntax, 1, 2, 0, /*
1005 Verify the syntax of entry BUTTON in a toolbar description list.
1006 If you want to verify the syntax of a toolbar description list as a
1007 whole, use `check-valid-instantiator' with a specifier type of 'toolbar.
1008 */
1009 (button, no_error))
1010 {
1011 Lisp_Object *elt, glyphs, value;
1012 int len;
1013 Error_behavior errb = decode_error_behavior_flag (no_error);
1014
1015 if (!VECTORP (button))
1016 CTB_ERROR ("toolbar button descriptors must be vectors");
1017 elt = XVECTOR_DATA (button);
1018
1019 if (XVECTOR_LENGTH (button) == 2)
1020 {
1021 if (!EQ (Q_style, check_toolbar_button_keywords (button, elt[0],
1022 elt[1], errb)))
1023 CTB_ERROR ("must specify toolbar blank style");
1024
1025 return Qt;
1026 }
1027
1028 if (XVECTOR_LENGTH (button) != 4)
1029 CTB_ERROR ("toolbar button descriptors must be 2 or 4 long");
1030
1031 /* The first element must be a list of glyphs of length 1-6. The
1032 first entry is the pixmap for the up state, the second for the
1033 down state, the third for the disabled state, the fourth for the
1034 captioned up state, the fifth for the captioned down state and
1035 the sixth for the captioned disabled state. Only the up state is
1036 mandatory. */
1037 if (!CONSP (elt[0]))
1038 {
1039 /* We can't check the buffer-local here because we don't know
1040 which buffer to check in. #### I think this is a bad thing.
1041 See if we can't get enough information to this function so
1042 that it can check.
1043
1044 #### Wrong. We shouldn't be checking the value at all here.
1045 The user might set or change the value at any time. */
1046 value = Fsymbol_value (elt[0]);
1047
1048 if (!CONSP (value))
1049 {
1050 if (KEYWORDP (elt[0]))
1051 {
1052 int fsty = 0;
1053
1054 if (EQ (Q_style, check_toolbar_button_keywords (button, elt[0],
1055 elt[1],
1056 errb)))
1057 fsty++;
1058
1059 if (EQ (Q_style, check_toolbar_button_keywords (button, elt[2],
1060 elt[3],
1061 errb)))
1062 fsty++;
1063
1064 if (!fsty)
1065 CTB_ERROR ("must specify toolbar blank style");
1066 else if (EQ (elt[0], elt[2]))
1067 CTB_ERROR
1068 ("duplicate keywords in toolbar button blank description");
1069
1070 return Qt;
1071 }
1072 else
1073 CTB_ERROR ("first element of button must be a list (of glyphs)");
1074 }
1075 }
1076 else
1077 value = elt[0];
1078
1079 len = XINT (Flength (value));
1080 if (len < 1)
1081 CTB_ERROR ("toolbar button glyph list must have at least 1 entry");
1082
1083 if (len > 6)
1084 CTB_ERROR ("toolbar button glyph list can have at most 6 entries");
1085
1086 glyphs = value;
1087 while (!NILP (glyphs))
1088 {
1089 if (!GLYPHP (XCAR (glyphs)))
1090 {
1091 /* We allow nil for the down and disabled glyphs but not for
1092 the up glyph. */
1093 if (EQ (glyphs, value) || !NILP (XCAR (glyphs)))
1094 {
1095 CTB_ERROR
1096 ("all elements of toolbar button glyph list must be glyphs.");
1097 }
1098 }
1099 glyphs = XCDR (glyphs);
1100 }
1101
1102 /* The second element is the function to run when the button is
1103 activated. We do not do any checking on it because it is legal
1104 for the function to not be defined until after the toolbar is.
1105 It is the user's problem to get this right.
1106
1107 The third element is either a boolean indicating the enabled
1108 status or a function used to determine it. Again, it is the
1109 user's problem if this is wrong.
1110
1111 The fourth element, if not nil, must be a string which will be
1112 displayed as the help echo. */
1113
1114 /* #### This should be allowed to be a function returning a string
1115 as well as just a string. */
1116 if (!NILP (elt[3]) && !STRINGP (elt[3]))
1117 CTB_ERROR ("toolbar button help echo string must be a string");
1118
1119 return Qt;
1120 }
1121 #undef CTB_ERROR
1122
1123 static void
1124 toolbar_validate (Lisp_Object instantiator)
1125 {
1126 int pushright_seen = 0;
1127 Lisp_Object rest;
1128
1129 if (NILP (instantiator))
1130 return;
1131
1132 if (!CONSP (instantiator))
1133 signal_simple_error ("Toolbar spec must be list or nil", instantiator);
1134
1135 for (rest = instantiator; !NILP (rest); rest = XCDR (rest))
1136 {
1137 if (!CONSP (rest))
1138 signal_simple_error ("Bad list in toolbar spec", instantiator);
1139
1140 if (NILP (XCAR (rest)))
1141 {
1142 if (pushright_seen)
1143 error
1144 ("More than one partition (nil) in instantiator description");
1145 else
1146 pushright_seen = 1;
1147 }
1148 else
1149 Fcheck_toolbar_button_syntax (XCAR (rest), Qnil);
1150 }
1151 }
1152
1153 static void
1154 toolbar_after_change (Lisp_Object specifier, Lisp_Object locale)
1155 {
1156 /* #### This is overkill. I really need to rethink the after-change
1157 functions to make them easier to use. */
1158 MARK_TOOLBAR_CHANGED;
1159 }
1160
1161 DEFUN ("toolbar-specifier-p", Ftoolbar_specifier_p, 1, 1, 0, /*
1162 Return non-nil if OBJECT is a toolbar specifier.
1163 Toolbar specifiers are used to specify the format of a toolbar.
1164 The values of the variables `default-toolbar', `top-toolbar',
1165 `left-toolbar', `right-toolbar', and `bottom-toolbar' are always
1166 toolbar specifiers.
1167
1168 Valid toolbar instantiators are called "toolbar descriptors"
1169 and are lists of vectors. See `default-toolbar' for a description
1170 of the exact format.
1171 */
1172 (object))
1173 {
1174 return TOOLBAR_SPECIFIERP (object) ? Qt : Qnil;
1175 }
1176
1177
1178 /*
1179 Helper for invalidating the real specifier when default
1180 specifier caching changes
1181 */
1182 static void
1183 recompute_overlaying_specifier (Lisp_Object real_one[4])
1184 {
1185 enum toolbar_pos pos = decode_toolbar_position (Vdefault_toolbar_position);
1186 Fset_specifier_dirty_flag (real_one[pos]);
1187 }
1188
1189 static void
1190 toolbar_specs_changed (Lisp_Object specifier, struct window *w,
1191 Lisp_Object oldval)
1192 {
1193 /* This could be smarter but I doubt that it would make any
1194 noticeable difference given the infrequency with which this is
1195 probably going to be called.
1196 */
1197 MARK_TOOLBAR_CHANGED;
1198 }
1199
1200 static void
1201 default_toolbar_specs_changed (Lisp_Object specifier, struct window *w,
1202 Lisp_Object oldval)
1203 {
1204 recompute_overlaying_specifier (Vtoolbar);
1205 }
1206
1207 static void
1208 default_toolbar_size_changed_in_frame (Lisp_Object specifier, struct frame *f,
1209 Lisp_Object oldval)
1210 {
1211 recompute_overlaying_specifier (Vtoolbar_size);
1212 }
1213
1214 static void
1215 default_toolbar_border_width_changed_in_frame (Lisp_Object specifier,
1216 struct frame *f,
1217 Lisp_Object oldval)
1218 {
1219 recompute_overlaying_specifier (Vtoolbar_border_width);
1220 }
1221
1222 static void
1223 default_toolbar_visible_p_changed_in_frame (Lisp_Object specifier,
1224 struct frame *f,
1225 Lisp_Object oldval)
1226 {
1227 recompute_overlaying_specifier (Vtoolbar_visible_p);
1228 }
1229
1230 static void
1231 toolbar_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
1232 Lisp_Object oldval)
1233 {
1234 MARK_TOOLBAR_CHANGED;
1235 MARK_WINDOWS_CHANGED (w);
1236 }
1237
1238 static void
1239 default_toolbar_size_changed_in_window (Lisp_Object specifier, struct window *w,
1240 Lisp_Object oldval)
1241 {
1242 recompute_overlaying_specifier (Vtoolbar_size);
1243 }
1244
1245 static void
1246 default_toolbar_border_width_changed_in_window (Lisp_Object specifier,
1247 struct window *w,
1248 Lisp_Object oldval)
1249 {
1250 recompute_overlaying_specifier (Vtoolbar_border_width);
1251 }
1252
1253 static void
1254 default_toolbar_visible_p_changed_in_window (Lisp_Object specifier,
1255 struct window *w,
1256 Lisp_Object oldval)
1257 {
1258 recompute_overlaying_specifier (Vtoolbar_visible_p);
1259 }
1260
1261 static void
1262 toolbar_buttons_captioned_p_changed (Lisp_Object specifier, struct window *w,
1263 Lisp_Object oldval)
1264 {
1265 /* This could be smarter but I doubt that it would make any
1266 noticeable difference given the infrequency with which this is
1267 probably going to be called. */
1268 MARK_TOOLBAR_CHANGED;
1269 }
1270
1271
1272 void
1273 syms_of_toolbar (void)
1274 {
1275 defsymbol (&Qtoolbar_buttonp, "toolbar-button-p");
1276 defsymbol (&Q2D, "2D");
1277 defsymbol (&Q3D, "3D");
1278 defsymbol (&Q2d, "2d");
1279 defsymbol (&Q3d, "3d");
1280 defsymbol (&Q_size, ":size"); Fset (Q_size, Q_size);
1281
1282 defsymbol (&Qinit_toolbar_from_resources, "init-toolbar-from-resources");
1283 DEFSUBR (Ftoolbar_button_p);
1284 DEFSUBR (Ftoolbar_button_callback);
1285 DEFSUBR (Ftoolbar_button_help_string);
1286 DEFSUBR (Ftoolbar_button_enabled_p);
1287 DEFSUBR (Fset_toolbar_button_down_flag);
1288 DEFSUBR (Fcheck_toolbar_button_syntax);
1289 DEFSUBR (Fset_default_toolbar_position);
1290 DEFSUBR (Fdefault_toolbar_position);
1291 DEFSUBR (Ftoolbar_specifier_p);
1292 }
1293
1294 void
1295 vars_of_toolbar (void)
1296 {
1297 staticpro (&Vdefault_toolbar_position);
1298 Vdefault_toolbar_position = Qtop;
1299
1300 #ifdef HAVE_WINDOW_SYSTEM
1301 Fprovide (Qtoolbar);
1302 #endif
1303 }
1304
1305 void
1306 specifier_type_create_toolbar (void)
1307 {
1308 INITIALIZE_SPECIFIER_TYPE (toolbar, "toolbar", "toolbar-specifier-p");
1309
1310 SPECIFIER_HAS_METHOD (toolbar, validate);
1311 SPECIFIER_HAS_METHOD (toolbar, after_change);
1312 }
1313
1314 void
1315 reinit_specifier_type_create_toolbar (void)
1316 {
1317 REINITIALIZE_SPECIFIER_TYPE (toolbar);
1318 }
1319
1320 void
1321 specifier_vars_of_toolbar (void)
1322 {
1323 Lisp_Object fb;
1324
1325 DEFVAR_SPECIFIER ("default-toolbar", &Vdefault_toolbar /*
1326 Specifier for a fallback toolbar.
1327 Use `set-specifier' to change this.
1328
1329 The position of this toolbar is specified in the function
1330 `default-toolbar-position'. If the corresponding position-specific
1331 toolbar (e.g. `top-toolbar' if `default-toolbar-position' is 'top)
1332 does not specify a toolbar in a particular domain (usually a window),
1333 then the value of `default-toolbar' in that domain, if any, will be
1334 used instead.
1335
1336 Note that the toolbar at any particular position will not be
1337 displayed unless its visibility flag is true and its thickness
1338 \(width or height, depending on orientation) is non-zero. The
1339 visibility is controlled by the specifiers `top-toolbar-visible-p',
1340 `bottom-toolbar-visible-p', `left-toolbar-visible-p', and
1341 `right-toolbar-visible-p', and the thickness is controlled by the
1342 specifiers `top-toolbar-height', `bottom-toolbar-height',
1343 `left-toolbar-width', and `right-toolbar-width'.
1344
1345 Note that one of the four visibility specifiers inherits from
1346 `default-toolbar-visibility' and one of the four thickness
1347 specifiers inherits from either `default-toolbar-width' or
1348 `default-toolbar-height' (depending on orientation), just
1349 like for the toolbar description specifiers (e.g. `top-toolbar')
1350 mentioned above.
1351
1352 Therefore, if you are setting `default-toolbar', you should control
1353 the visibility and thickness using `default-toolbar-visible-p',
1354 `default-toolbar-width', and `default-toolbar-height', rather than
1355 using position-specific specifiers. That way, you will get sane
1356 behavior if the user changes the default toolbar position.
1357
1358 The format of the instantiator for a toolbar is a list of
1359 toolbar-button-descriptors. Each toolbar-button-descriptor
1360 is a vector in one of the following formats:
1361
1362 [GLYPH-LIST FUNCTION ENABLED-P HELP] or
1363 [:style 2D-OR-3D] or
1364 [:style 2D-OR-3D :size WIDTH-OR-HEIGHT] or
1365 [:size WIDTH-OR-HEIGHT :style 2D-OR-3D]
1366
1367 Optionally, one of the toolbar-button-descriptors may be nil
1368 instead of a vector; this signifies the division between
1369 the toolbar buttons that are to be displayed flush-left,
1370 and the buttons to be displayed flush-right.
1371
1372 The first vector format above specifies a normal toolbar button;
1373 the others specify blank areas in the toolbar.
1374
1375 For the first vector format:
1376
1377 -- GLYPH-LIST should be a list of one to six glyphs (as created by
1378 `make-glyph') or a symbol whose value is such a list. The first
1379 glyph, which must be provided, is the glyph used to display the
1380 toolbar button when it is in the "up" (not pressed) state. The
1381 optional second glyph is for displaying the button when it is in
1382 the "down" (pressed) state. The optional third glyph is for when
1383 the button is disabled. The optional fourth, fifth and sixth glyphs
1384 are used to specify captioned versions for the up, down and disabled
1385 states respectively. The function `toolbar-make-button-list' is
1386 useful in creating these glyph lists. The specifier variable
1387 `toolbar-buttons-captioned-p' controls which glyphs are actually used.
1388
1389 -- Even if you do not provide separate down-state and disabled-state
1390 glyphs, the user will still get visual feedback to indicate which
1391 state the button is in. Buttons in the up-state are displayed
1392 with a shadowed border that gives a raised appearance to the
1393 button. Buttons in the down-state are displayed with shadows that
1394 give a recessed appearance. Buttons in the disabled state are
1395 displayed with no shadows, giving a 2-d effect.
1396
1397 -- If some of the toolbar glyphs are not provided, they inherit as follows:
1398
1399 UP: up
1400 DOWN: down -> up
1401 DISABLED: disabled -> up
1402 CAP-UP: cap-up -> up
1403 CAP-DOWN: cap-down -> cap-up -> down -> up
1404 CAP-DISABLED: cap-disabled -> cap-up -> disabled -> up
1405
1406 -- The second element FUNCTION is a function to be called when the
1407 toolbar button is activated (i.e. when the mouse is released over
1408 the toolbar button, if the press occurred in the toolbar). It
1409 can be any form accepted by `call-interactively', since this is
1410 how it is invoked.
1411
1412 -- The third element ENABLED-P specifies whether the toolbar button
1413 is enabled (disabled buttons do nothing when they are activated,
1414 and are displayed differently; see above). It should be either
1415 a boolean or a form that evaluates to a boolean.
1416
1417 -- The fourth element HELP, if non-nil, should be a string. This
1418 string is displayed in the echo area when the mouse passes over
1419 the toolbar button.
1420
1421 For the other vector formats (specifying blank areas of the toolbar):
1422
1423 -- 2D-OR-3D should be one of the symbols '2d or '3d, indicating
1424 whether the area is displayed with shadows (giving it a raised,
1425 3-d appearance) or without shadows (giving it a flat appearance).
1426
1427 -- WIDTH-OR-HEIGHT specifies the length, in pixels, of the blank
1428 area. If omitted, it defaults to a device-specific value
1429 (8 pixels for X devices).
1430 */ );
1431
1432 Vdefault_toolbar = Fmake_specifier (Qtoolbar);
1433 /* #### It would be even nicer if the specifier caching
1434 automatically knew about specifier fallbacks, so we didn't
1435 have to do it ourselves. */
1436 set_specifier_caching (Vdefault_toolbar,
1437 slot_offset (struct window,
1438 default_toolbar),
1439 default_toolbar_specs_changed,
1440 0, 0);
1441
1442 DEFVAR_SPECIFIER ("top-toolbar",
1443 &Vtoolbar[TOP_TOOLBAR] /*
1444 Specifier for the toolbar at the top of the frame.
1445 Use `set-specifier' to change this.
1446 See `default-toolbar' for a description of a valid toolbar instantiator.
1447 */ );
1448 Vtoolbar[TOP_TOOLBAR] = Fmake_specifier (Qtoolbar);
1449 set_specifier_caching (Vtoolbar[TOP_TOOLBAR],
1450 slot_offset (struct window,
1451 toolbar[TOP_TOOLBAR]),
1452 toolbar_specs_changed,
1453 0, 0);
1454
1455 DEFVAR_SPECIFIER ("bottom-toolbar",
1456 &Vtoolbar[BOTTOM_TOOLBAR] /*
1457 Specifier for the toolbar at the bottom of the frame.
1458 Use `set-specifier' to change this.
1459 See `default-toolbar' for a description of a valid toolbar instantiator.
1460
1461 Note that, unless the `default-toolbar-position' is `bottom', by
1462 default the height of the bottom toolbar (controlled by
1463 `bottom-toolbar-height') is 0; thus, a bottom toolbar will not be
1464 displayed even if you provide a value for `bottom-toolbar'.
1465 */ );
1466 Vtoolbar[BOTTOM_TOOLBAR] = Fmake_specifier (Qtoolbar);
1467 set_specifier_caching (Vtoolbar[BOTTOM_TOOLBAR],
1468 slot_offset (struct window,
1469 toolbar[BOTTOM_TOOLBAR]),
1470 toolbar_specs_changed,
1471 0, 0);
1472
1473 DEFVAR_SPECIFIER ("left-toolbar",
1474 &Vtoolbar[LEFT_TOOLBAR] /*
1475 Specifier for the toolbar at the left edge of the frame.
1476 Use `set-specifier' to change this.
1477 See `default-toolbar' for a description of a valid toolbar instantiator.
1478
1479 Note that, unless the `default-toolbar-position' is `left', by
1480 default the height of the left toolbar (controlled by
1481 `left-toolbar-width') is 0; thus, a left toolbar will not be
1482 displayed even if you provide a value for `left-toolbar'.
1483 */ );
1484 Vtoolbar[LEFT_TOOLBAR] = Fmake_specifier (Qtoolbar);
1485 set_specifier_caching (Vtoolbar[LEFT_TOOLBAR],
1486 slot_offset (struct window,
1487 toolbar[LEFT_TOOLBAR]),
1488 toolbar_specs_changed,
1489 0, 0);
1490
1491 DEFVAR_SPECIFIER ("right-toolbar",
1492 &Vtoolbar[RIGHT_TOOLBAR] /*
1493 Specifier for the toolbar at the right edge of the frame.
1494 Use `set-specifier' to change this.
1495 See `default-toolbar' for a description of a valid toolbar instantiator.
1496
1497 Note that, unless the `default-toolbar-position' is `right', by
1498 default the height of the right toolbar (controlled by
1499 `right-toolbar-width') is 0; thus, a right toolbar will not be
1500 displayed even if you provide a value for `right-toolbar'.
1501 */ );
1502 Vtoolbar[RIGHT_TOOLBAR] = Fmake_specifier (Qtoolbar);
1503 set_specifier_caching (Vtoolbar[RIGHT_TOOLBAR],
1504 slot_offset (struct window,
1505 toolbar[RIGHT_TOOLBAR]),
1506 toolbar_specs_changed,
1507 0, 0);
1508
1509 /* initially, top inherits from default; this can be
1510 changed with `set-default-toolbar-position'. */
1511 fb = list1 (Fcons (Qnil, Qnil));
1512 set_specifier_fallback (Vdefault_toolbar, fb);
1513 set_specifier_fallback (Vtoolbar[TOP_TOOLBAR], Vdefault_toolbar);
1514 set_specifier_fallback (Vtoolbar[BOTTOM_TOOLBAR], fb);
1515 set_specifier_fallback (Vtoolbar[LEFT_TOOLBAR], fb);
1516 set_specifier_fallback (Vtoolbar[RIGHT_TOOLBAR], fb);
1517
1518 DEFVAR_SPECIFIER ("default-toolbar-height", &Vdefault_toolbar_height /*
1519 *Height of the default toolbar, if it's oriented horizontally.
1520 This is a specifier; use `set-specifier' to change it.
1521
1522 The position of the default toolbar is specified by the function
1523 `set-default-toolbar-position'. If the corresponding position-specific
1524 toolbar thickness specifier (e.g. `top-toolbar-height' if
1525 `default-toolbar-position' is 'top) does not specify a thickness in a
1526 particular domain (a window or a frame), then the value of
1527 `default-toolbar-height' or `default-toolbar-width' (depending on the
1528 toolbar orientation) in that domain, if any, will be used instead.
1529
1530 Note that `default-toolbar-height' is only used when
1531 `default-toolbar-position' is 'top or 'bottom, and `default-toolbar-width'
1532 is only used when `default-toolbar-position' is 'left or 'right.
1533
1534 Note that all of the position-specific toolbar thickness specifiers
1535 have a fallback value of zero when they do not correspond to the
1536 default toolbar. Therefore, you will have to set a non-zero thickness
1537 value if you want a position-specific toolbar to be displayed.
1538
1539 Internally, toolbar thickness specifiers are instantiated in both
1540 window and frame domains, for different purposes. The value in the
1541 domain of a frame's selected window specifies the actual toolbar
1542 thickness that you will see in that frame. The value in the domain of
1543 a frame itself specifies the toolbar thickness that is used in frame
1544 geometry calculations.
1545
1546 Thus, for example, if you set the frame width to 80 characters and the
1547 left toolbar width for that frame to 68 pixels, then the frame will
1548 be sized to fit 80 characters plus a 68-pixel left toolbar. If you
1549 then set the left toolbar width to 0 for a particular buffer (or if
1550 that buffer does not specify a left toolbar or has a nil value
1551 specified for `left-toolbar-visible-p'), you will find that, when
1552 that buffer is displayed in the selected window, the window will have
1553 a width of 86 or 87 characters -- the frame is sized for a 68-pixel
1554 left toolbar but the selected window specifies that the left toolbar
1555 is not visible, so it is expanded to take up the slack.
1556 */ );
1557 Vdefault_toolbar_height = Fmake_specifier (Qnatnum);
1558 set_specifier_caching (Vdefault_toolbar_height,
1559 slot_offset (struct window,
1560 default_toolbar_height),
1561 default_toolbar_size_changed_in_window,
1562 slot_offset (struct frame,
1563 default_toolbar_height),
1564 default_toolbar_size_changed_in_frame);
1565
1566 DEFVAR_SPECIFIER ("default-toolbar-width", &Vdefault_toolbar_width /*
1567 *Width of the default toolbar, if it's oriented vertically.
1568 This is a specifier; use `set-specifier' to change it.
1569
1570 See `default-toolbar-height' for more information.
1571 */ );
1572 Vdefault_toolbar_width = Fmake_specifier (Qnatnum);
1573 set_specifier_caching (Vdefault_toolbar_width,
1574 slot_offset (struct window,
1575 default_toolbar_width),
1576 default_toolbar_size_changed_in_window,
1577 slot_offset (struct frame,
1578 default_toolbar_width),
1579 default_toolbar_size_changed_in_frame);
1580
1581 DEFVAR_SPECIFIER ("top-toolbar-height",
1582 &Vtoolbar_size[TOP_TOOLBAR] /*
1583 *Height of the top toolbar.
1584 This is a specifier; use `set-specifier' to change it.
1585
1586 See `default-toolbar-height' for more information.
1587 */ );
1588 Vtoolbar_size[TOP_TOOLBAR] = Fmake_specifier (Qnatnum);
1589 set_specifier_caching (Vtoolbar_size[TOP_TOOLBAR],
1590 slot_offset (struct window,
1591 toolbar_size[TOP_TOOLBAR]),
1592 toolbar_geometry_changed_in_window,
1593 slot_offset (struct frame,
1594 toolbar_size[TOP_TOOLBAR]),
1595 frame_size_slipped);
1596
1597 DEFVAR_SPECIFIER ("bottom-toolbar-height",
1598 &Vtoolbar_size[BOTTOM_TOOLBAR] /*
1599 *Height of the bottom toolbar.
1600 This is a specifier; use `set-specifier' to change it.
1601
1602 See `default-toolbar-height' for more information.
1603 */ );
1604 Vtoolbar_size[BOTTOM_TOOLBAR] = Fmake_specifier (Qnatnum);
1605 set_specifier_caching (Vtoolbar_size[BOTTOM_TOOLBAR],
1606 slot_offset (struct window,
1607 toolbar_size[BOTTOM_TOOLBAR]),
1608 toolbar_geometry_changed_in_window,
1609 slot_offset (struct frame,
1610 toolbar_size[BOTTOM_TOOLBAR]),
1611 frame_size_slipped);
1612
1613 DEFVAR_SPECIFIER ("left-toolbar-width",
1614 &Vtoolbar_size[LEFT_TOOLBAR] /*
1615 *Width of left toolbar.
1616 This is a specifier; use `set-specifier' to change it.
1617
1618 See `default-toolbar-height' for more information.
1619 */ );
1620 Vtoolbar_size[LEFT_TOOLBAR] = Fmake_specifier (Qnatnum);
1621 set_specifier_caching (Vtoolbar_size[LEFT_TOOLBAR],
1622 slot_offset (struct window,
1623 toolbar_size[LEFT_TOOLBAR]),
1624 toolbar_geometry_changed_in_window,
1625 slot_offset (struct frame,
1626 toolbar_size[LEFT_TOOLBAR]),
1627 frame_size_slipped);
1628
1629 DEFVAR_SPECIFIER ("right-toolbar-width",
1630 &Vtoolbar_size[RIGHT_TOOLBAR] /*
1631 *Width of right toolbar.
1632 This is a specifier; use `set-specifier' to change it.
1633
1634 See `default-toolbar-height' for more information.
1635 */ );
1636 Vtoolbar_size[RIGHT_TOOLBAR] = Fmake_specifier (Qnatnum);
1637 set_specifier_caching (Vtoolbar_size[RIGHT_TOOLBAR],
1638 slot_offset (struct window,
1639 toolbar_size[RIGHT_TOOLBAR]),
1640 toolbar_geometry_changed_in_window,
1641 slot_offset (struct frame,
1642 toolbar_size[RIGHT_TOOLBAR]),
1643 frame_size_slipped);
1644
1645 fb = Qnil;
1646 #ifdef HAVE_TTY
1647 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1648 #endif
1649 #ifdef HAVE_X_WINDOWS
1650 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_TOOLBAR_HEIGHT)), fb);
1651 #endif
1652 #ifdef HAVE_MS_WINDOWS
1653 fb = Fcons (Fcons (list1 (Qmswindows),
1654 make_int (MSWINDOWS_DEFAULT_TOOLBAR_HEIGHT)), fb);
1655 #endif
1656 if (!NILP (fb))
1657 set_specifier_fallback (Vdefault_toolbar_height, fb);
1658
1659 fb = Qnil;
1660 #ifdef HAVE_TTY
1661 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1662 #endif
1663 #ifdef HAVE_X_WINDOWS
1664 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_TOOLBAR_WIDTH)), fb);
1665 #endif
1666 #ifdef HAVE_MS_WINDOWS
1667 fb = Fcons (Fcons (list1 (Qmswindows),
1668 make_int (MSWINDOWS_DEFAULT_TOOLBAR_WIDTH)), fb);
1669 #endif
1670 if (!NILP (fb))
1671 set_specifier_fallback (Vdefault_toolbar_width, fb);
1672
1673 set_specifier_fallback (Vtoolbar_size[TOP_TOOLBAR], Vdefault_toolbar_height);
1674 fb = list1 (Fcons (Qnil, Qzero));
1675 set_specifier_fallback (Vtoolbar_size[BOTTOM_TOOLBAR], fb);
1676 set_specifier_fallback (Vtoolbar_size[LEFT_TOOLBAR], fb);
1677 set_specifier_fallback (Vtoolbar_size[RIGHT_TOOLBAR], fb);
1678
1679 DEFVAR_SPECIFIER ("default-toolbar-border-width",
1680 &Vdefault_toolbar_border_width /*
1681 *Width of the border around the default toolbar.
1682 This is a specifier; use `set-specifier' to change it.
1683
1684 The position of the default toolbar is specified by the function
1685 `set-default-toolbar-position'. If the corresponding position-specific
1686 toolbar border width specifier (e.g. `top-toolbar-border-width' if
1687 `default-toolbar-position' is 'top) does not specify a border width in a
1688 particular domain (a window or a frame), then the value of
1689 `default-toolbar-border-width' in that domain, if any, will be used
1690 instead.
1691
1692 Internally, toolbar border width specifiers are instantiated in both
1693 window and frame domains, for different purposes. The value in the
1694 domain of a frame's selected window specifies the actual toolbar border
1695 width that you will see in that frame. The value in the domain of a
1696 frame itself specifies the toolbar border width that is used in frame
1697 geometry calculations. Changing the border width value in the frame
1698 domain will result in a size change in the frame itself, while changing
1699 the value in a window domain will not.
1700 */ );
1701 Vdefault_toolbar_border_width = Fmake_specifier (Qnatnum);
1702 set_specifier_caching (Vdefault_toolbar_border_width,
1703 slot_offset (struct window,
1704 default_toolbar_border_width),
1705 default_toolbar_border_width_changed_in_window,
1706 slot_offset (struct frame,
1707 default_toolbar_border_width),
1708 default_toolbar_border_width_changed_in_frame);
1709
1710 DEFVAR_SPECIFIER ("top-toolbar-border-width",
1711 &Vtoolbar_border_width[TOP_TOOLBAR] /*
1712 *Border width of the top toolbar.
1713 This is a specifier; use `set-specifier' to change it.
1714
1715 See `default-toolbar-height' for more information.
1716 */ );
1717 Vtoolbar_border_width[TOP_TOOLBAR] = Fmake_specifier (Qnatnum);
1718 set_specifier_caching (Vtoolbar_border_width[TOP_TOOLBAR],
1719 slot_offset (struct window,
1720 toolbar_border_width[TOP_TOOLBAR]),
1721 toolbar_geometry_changed_in_window,
1722 slot_offset (struct frame,
1723 toolbar_border_width[TOP_TOOLBAR]),
1724 frame_size_slipped);
1725
1726 DEFVAR_SPECIFIER ("bottom-toolbar-border-width",
1727 &Vtoolbar_border_width[BOTTOM_TOOLBAR] /*
1728 *Border width of the bottom toolbar.
1729 This is a specifier; use `set-specifier' to change it.
1730
1731 See `default-toolbar-height' for more information.
1732 */ );
1733 Vtoolbar_border_width[BOTTOM_TOOLBAR] = Fmake_specifier (Qnatnum);
1734 set_specifier_caching (Vtoolbar_border_width[BOTTOM_TOOLBAR],
1735 slot_offset (struct window,
1736 toolbar_border_width[BOTTOM_TOOLBAR]),
1737 toolbar_geometry_changed_in_window,
1738 slot_offset (struct frame,
1739 toolbar_border_width[BOTTOM_TOOLBAR]),
1740 frame_size_slipped);
1741
1742 DEFVAR_SPECIFIER ("left-toolbar-border-width",
1743 &Vtoolbar_border_width[LEFT_TOOLBAR] /*
1744 *Border width of left toolbar.
1745 This is a specifier; use `set-specifier' to change it.
1746
1747 See `default-toolbar-height' for more information.
1748 */ );
1749 Vtoolbar_border_width[LEFT_TOOLBAR] = Fmake_specifier (Qnatnum);
1750 set_specifier_caching (Vtoolbar_border_width[LEFT_TOOLBAR],
1751 slot_offset (struct window,
1752 toolbar_border_width[LEFT_TOOLBAR]),
1753 toolbar_geometry_changed_in_window,
1754 slot_offset (struct frame,
1755 toolbar_border_width[LEFT_TOOLBAR]),
1756 frame_size_slipped);
1757
1758 DEFVAR_SPECIFIER ("right-toolbar-border-width",
1759 &Vtoolbar_border_width[RIGHT_TOOLBAR] /*
1760 *Border width of right toolbar.
1761 This is a specifier; use `set-specifier' to change it.
1762
1763 See `default-toolbar-height' for more information.
1764 */ );
1765 Vtoolbar_border_width[RIGHT_TOOLBAR] = Fmake_specifier (Qnatnum);
1766 set_specifier_caching (Vtoolbar_border_width[RIGHT_TOOLBAR],
1767 slot_offset (struct window,
1768 toolbar_border_width[RIGHT_TOOLBAR]),
1769 toolbar_geometry_changed_in_window,
1770 slot_offset (struct frame,
1771 toolbar_border_width[RIGHT_TOOLBAR]),
1772 frame_size_slipped);
1773
1774 fb = Qnil;
1775 #ifdef HAVE_TTY
1776 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1777 #endif
1778 #ifdef HAVE_X_WINDOWS
1779 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_TOOLBAR_BORDER_WIDTH)), fb);
1780 #endif
1781 #ifdef HAVE_MS_WINDOWS
1782 fb = Fcons (Fcons (list1 (Qmswindows), make_int (MSWINDOWS_DEFAULT_TOOLBAR_BORDER_WIDTH)), fb);
1783 #endif
1784 if (!NILP (fb))
1785 set_specifier_fallback (Vdefault_toolbar_border_width, fb);
1786
1787 set_specifier_fallback (Vtoolbar_border_width[TOP_TOOLBAR], Vdefault_toolbar_border_width);
1788 fb = list1 (Fcons (Qnil, Qzero));
1789 set_specifier_fallback (Vtoolbar_border_width[BOTTOM_TOOLBAR], fb);
1790 set_specifier_fallback (Vtoolbar_border_width[LEFT_TOOLBAR], fb);
1791 set_specifier_fallback (Vtoolbar_border_width[RIGHT_TOOLBAR], fb);
1792
1793 DEFVAR_SPECIFIER ("default-toolbar-visible-p", &Vdefault_toolbar_visible_p /*
1794 *Whether the default toolbar is visible.
1795 This is a specifier; use `set-specifier' to change it.
1796
1797 The position of the default toolbar is specified by the function
1798 `set-default-toolbar-position'. If the corresponding position-specific
1799 toolbar visibility specifier (e.g. `top-toolbar-visible-p' if
1800 `default-toolbar-position' is 'top) does not specify a visible-p value
1801 in a particular domain (a window or a frame), then the value of
1802 `default-toolbar-visible-p' in that domain, if any, will be used
1803 instead.
1804
1805 Both window domains and frame domains are used internally, for
1806 different purposes. The distinction here is exactly the same as
1807 for thickness specifiers; see `default-toolbar-height' for more
1808 information.
1809
1810 `default-toolbar-visible-p' and all of the position-specific toolbar
1811 visibility specifiers have a fallback value of true.
1812 */ );
1813 Vdefault_toolbar_visible_p = Fmake_specifier (Qboolean);
1814 set_specifier_caching (Vdefault_toolbar_visible_p,
1815 slot_offset (struct window,
1816 default_toolbar_visible_p),
1817 default_toolbar_visible_p_changed_in_window,
1818 slot_offset (struct frame,
1819 default_toolbar_visible_p),
1820 default_toolbar_visible_p_changed_in_frame);
1821
1822 DEFVAR_SPECIFIER ("top-toolbar-visible-p",
1823 &Vtoolbar_visible_p[TOP_TOOLBAR] /*
1824 *Whether the top toolbar is visible.
1825 This is a specifier; use `set-specifier' to change it.
1826
1827 See `default-toolbar-visible-p' for more information.
1828 */ );
1829 Vtoolbar_visible_p[TOP_TOOLBAR] = Fmake_specifier (Qboolean);
1830 set_specifier_caching (Vtoolbar_visible_p[TOP_TOOLBAR],
1831 slot_offset (struct window,
1832 toolbar_visible_p[TOP_TOOLBAR]),
1833 toolbar_geometry_changed_in_window,
1834 slot_offset (struct frame,
1835 toolbar_visible_p[TOP_TOOLBAR]),
1836 frame_size_slipped);
1837
1838 DEFVAR_SPECIFIER ("bottom-toolbar-visible-p",
1839 &Vtoolbar_visible_p[BOTTOM_TOOLBAR] /*
1840 *Whether the bottom toolbar is visible.
1841 This is a specifier; use `set-specifier' to change it.
1842
1843 See `default-toolbar-visible-p' for more information.
1844 */ );
1845 Vtoolbar_visible_p[BOTTOM_TOOLBAR] = Fmake_specifier (Qboolean);
1846 set_specifier_caching (Vtoolbar_visible_p[BOTTOM_TOOLBAR],
1847 slot_offset (struct window,
1848 toolbar_visible_p[BOTTOM_TOOLBAR]),
1849 toolbar_geometry_changed_in_window,
1850 slot_offset (struct frame,
1851 toolbar_visible_p[BOTTOM_TOOLBAR]),
1852 frame_size_slipped);
1853
1854 DEFVAR_SPECIFIER ("left-toolbar-visible-p",
1855 &Vtoolbar_visible_p[LEFT_TOOLBAR] /*
1856 *Whether the left toolbar is visible.
1857 This is a specifier; use `set-specifier' to change it.
1858
1859 See `default-toolbar-visible-p' for more information.
1860 */ );
1861 Vtoolbar_visible_p[LEFT_TOOLBAR] = Fmake_specifier (Qboolean);
1862 set_specifier_caching (Vtoolbar_visible_p[LEFT_TOOLBAR],
1863 slot_offset (struct window,
1864 toolbar_visible_p[LEFT_TOOLBAR]),
1865 toolbar_geometry_changed_in_window,
1866 slot_offset (struct frame,
1867 toolbar_visible_p[LEFT_TOOLBAR]),
1868 frame_size_slipped);
1869
1870 DEFVAR_SPECIFIER ("right-toolbar-visible-p",
1871 &Vtoolbar_visible_p[RIGHT_TOOLBAR] /*
1872 *Whether the right toolbar is visible.
1873 This is a specifier; use `set-specifier' to change it.
1874
1875 See `default-toolbar-visible-p' for more information.
1876 */ );
1877 Vtoolbar_visible_p[RIGHT_TOOLBAR] = Fmake_specifier (Qboolean);
1878 set_specifier_caching (Vtoolbar_visible_p[RIGHT_TOOLBAR],
1879 slot_offset (struct window,
1880 toolbar_visible_p[RIGHT_TOOLBAR]),
1881 toolbar_geometry_changed_in_window,
1882 slot_offset (struct frame,
1883 toolbar_visible_p[RIGHT_TOOLBAR]),
1884 frame_size_slipped);
1885
1886 /* initially, top inherits from default; this can be
1887 changed with `set-default-toolbar-position'. */
1888 fb = list1 (Fcons (Qnil, Qt));
1889 set_specifier_fallback (Vdefault_toolbar_visible_p, fb);
1890 set_specifier_fallback (Vtoolbar_visible_p[TOP_TOOLBAR],
1891 Vdefault_toolbar_visible_p);
1892 set_specifier_fallback (Vtoolbar_visible_p[BOTTOM_TOOLBAR], fb);
1893 set_specifier_fallback (Vtoolbar_visible_p[LEFT_TOOLBAR], fb);
1894 set_specifier_fallback (Vtoolbar_visible_p[RIGHT_TOOLBAR], fb);
1895
1896 DEFVAR_SPECIFIER ("toolbar-buttons-captioned-p",
1897 &Vtoolbar_buttons_captioned_p /*
1898 *Whether the toolbar buttons are captioned.
1899 This will only have a visible effect for those toolbar buttons which had
1900 captioned versions specified.
1901 This is a specifier; use `set-specifier' to change it.
1902 */ );
1903 Vtoolbar_buttons_captioned_p = Fmake_specifier (Qboolean);
1904 set_specifier_caching (Vtoolbar_buttons_captioned_p,
1905 slot_offset (struct window,
1906 toolbar_buttons_captioned_p),
1907 toolbar_buttons_captioned_p_changed,
1908 0, 0);
1909 set_specifier_fallback (Vtoolbar_buttons_captioned_p,
1910 list1 (Fcons (Qnil, Qt)));
1911 }