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.
7 This file is part of SXEmacs
9 SXEmacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 SXEmacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 /* Synched up with: Not in FSF. */
25 /* Original implementation by Chuck Thompson for 19.12.
26 Default-toolbar-position and specifier-related stuff by Ben Wing. */
35 #include "redisplay.h"
39 Lisp_Object Vtoolbar[4];
40 Lisp_Object Vtoolbar_size[4];
41 Lisp_Object Vtoolbar_visible_p[4];
42 Lisp_Object Vtoolbar_border_width[4];
44 Lisp_Object Vdefault_toolbar, Vdefault_toolbar_visible_p;
45 Lisp_Object Vdefault_toolbar_width, Vdefault_toolbar_height;
46 Lisp_Object Vdefault_toolbar_border_width;
48 Lisp_Object Vdefault_toolbar_position;
49 Lisp_Object Vtoolbar_buttons_captioned_p;
51 Lisp_Object Qtoolbar_buttonp;
52 Lisp_Object Q2D, Q3D, Q2d, Q3d;
55 Lisp_Object Qinit_toolbar_from_resources;
57 static Lisp_Object mark_toolbar_button(Lisp_Object obj)
59 struct toolbar_button *data = XTOOLBAR_BUTTON(obj);
60 mark_object(data->next);
61 mark_object(data->frame);
62 mark_object(data->up_glyph);
63 mark_object(data->down_glyph);
64 mark_object(data->disabled_glyph);
65 mark_object(data->cap_up_glyph);
66 mark_object(data->cap_down_glyph);
67 mark_object(data->cap_disabled_glyph);
68 mark_object(data->callback);
69 mark_object(data->enabled_p);
70 return data->help_string;
73 DEFINE_LRECORD_IMPLEMENTATION("toolbar-button", toolbar_button,
74 mark_toolbar_button, 0, 0, 0, 0, 0,
75 struct toolbar_button);
77 DEFUN("toolbar-button-p", Ftoolbar_button_p, 1, 1, 0, /*
78 Return non-nil if OBJECT is a toolbar button.
82 return TOOLBAR_BUTTONP(object) ? Qt : Qnil;
85 /* Only query functions are provided for toolbar buttons. They are
86 generated and updated from a toolbar description list. Any
87 directly made changes would be wiped out the first time the toolbar
88 was marked as dirty and was regenerated. The exception to this is
89 set-toolbar-button-down-flag. Having this allows us to control the
90 toolbar from elisp. Since we only trigger the button callbacks on
91 up-mouse events and we reset the flag first, there shouldn't be any
92 way for this to get us in trouble (like if someone decides to
93 change the toolbar from a toolbar callback). */
95 DEFUN("toolbar-button-callback", Ftoolbar_button_callback, 1, 1, 0, /*
96 Return the callback function associated with the toolbar BUTTON.
100 CHECK_TOOLBAR_BUTTON(button);
102 return XTOOLBAR_BUTTON(button)->callback;
105 DEFUN("toolbar-button-help-string", Ftoolbar_button_help_string, 1, 1, 0, /*
106 Return the help string function associated with the toolbar BUTTON.
110 CHECK_TOOLBAR_BUTTON(button);
112 return XTOOLBAR_BUTTON(button)->help_string;
115 DEFUN("toolbar-button-enabled-p", Ftoolbar_button_enabled_p, 1, 1, 0, /*
116 Return t if BUTTON is active.
120 CHECK_TOOLBAR_BUTTON(button);
122 return XTOOLBAR_BUTTON(button)->enabled ? Qt : Qnil;
125 DEFUN("set-toolbar-button-down-flag", Fset_toolbar_button_down_flag, 2, 2, 0, /*
130 struct toolbar_button *tb;
133 CHECK_TOOLBAR_BUTTON(button);
134 tb = XTOOLBAR_BUTTON(button);
137 /* If the button is ignored, don't do anything. */
141 /* If flag is nil, unset the down flag, otherwise set it to true.
142 This also triggers an immediate redraw of the button if the flag
150 if (tb->down != old_flag) {
151 struct frame *f = XFRAME(tb->frame);
154 if (DEVICEP(f->device)) {
155 d = XDEVICE(f->device);
157 if (DEVICE_LIVE_P(XDEVICE(f->device))) {
159 MAYBE_DEVMETH(d, output_toolbar_button,
169 get_toolbar_button_glyph(struct window * w, struct toolbar_button * tb)
171 Lisp_Object glyph = Qnil;
173 /* The selected glyph logic:
177 DISABLED: disabled -> up
179 CAP-DOWN: cap-down -> cap-up -> down -> up
180 CAP-DISABLED: cap-disabled -> cap-up -> disabled -> up
183 if (!NILP(w->toolbar_buttons_captioned_p)) {
184 if (tb->enabled && tb->down)
185 glyph = tb->cap_down_glyph;
186 else if (!tb->enabled)
187 glyph = tb->cap_disabled_glyph;
190 glyph = tb->cap_up_glyph;
194 if (tb->enabled && tb->down)
195 glyph = tb->down_glyph;
196 else if (!tb->enabled)
197 glyph = tb->disabled_glyph;
200 /* The non-captioned up button is the ultimate fallback. It is
201 the only one we guarantee exists. */
203 glyph = tb->up_glyph;
208 static enum toolbar_pos decode_toolbar_position(Lisp_Object position)
210 if (EQ(position, Qtop))
212 if (EQ(position, Qbottom))
213 return BOTTOM_TOOLBAR;
214 if (EQ(position, Qleft))
216 if (EQ(position, Qright))
217 return RIGHT_TOOLBAR;
218 signal_simple_error("Invalid toolbar position", position);
220 return TOP_TOOLBAR; /* not reached */
223 DEFUN("set-default-toolbar-position", Fset_default_toolbar_position, 1, 1, 0, /*
224 Set the position that the `default-toolbar' will be displayed at.
225 Valid positions are 'top, 'bottom, 'left and 'right.
226 See `default-toolbar-position'.
230 enum toolbar_pos cur =
231 decode_toolbar_position(Vdefault_toolbar_position);
232 enum toolbar_pos new = decode_toolbar_position(position);
235 /* The following calls will automatically cause the dirty
236 flags to be set; we delay frame size changes to avoid
237 lots of frame flickering. */
238 /* #### I think this should be GC protected. -sb */
239 hold_frame_size_changes();
240 set_specifier_fallback(Vtoolbar[cur], list1(Fcons(Qnil, Qnil)));
241 set_specifier_fallback(Vtoolbar[new], Vdefault_toolbar);
242 set_specifier_fallback(Vtoolbar_size[cur],
243 list1(Fcons(Qnil, Qzero)));
244 set_specifier_fallback(Vtoolbar_size[new], new == TOP_TOOLBAR
246 BOTTOM_TOOLBAR ? Vdefault_toolbar_height
247 : Vdefault_toolbar_width);
248 set_specifier_fallback(Vtoolbar_border_width[cur],
249 list1(Fcons(Qnil, Qzero)));
250 set_specifier_fallback(Vtoolbar_border_width[new],
251 Vdefault_toolbar_border_width);
252 set_specifier_fallback(Vtoolbar_visible_p[cur],
253 list1(Fcons(Qnil, Qt)));
254 set_specifier_fallback(Vtoolbar_visible_p[new],
255 Vdefault_toolbar_visible_p);
256 Vdefault_toolbar_position = position;
257 unhold_frame_size_changes();
263 DEFUN("default-toolbar-position", Fdefault_toolbar_position, 0, 0, 0, /*
264 Return the position that the `default-toolbar' will be displayed at.
265 The `default-toolbar' will only be displayed here if the corresponding
266 position-specific toolbar specifier does not provide a value.
270 return Vdefault_toolbar_position;
274 update_toolbar_button(struct frame *f, struct toolbar_button *tb,
275 Lisp_Object desc, int pushright)
277 Lisp_Object *elt, glyphs, retval, buffer;
278 struct gcpro gcpro1, gcpro2;
280 elt = XVECTOR_DATA(desc);
281 buffer = XWINDOW(FRAME_LAST_NONMINIBUF_WINDOW(f))->buffer;
284 tb = alloc_lcrecord_type(struct toolbar_button,
285 &lrecord_toolbar_button);
287 XSETFRAME(tb->frame, f);
289 tb->down_glyph = Qnil;
290 tb->disabled_glyph = Qnil;
291 tb->cap_up_glyph = Qnil;
292 tb->cap_down_glyph = Qnil;
293 tb->cap_disabled_glyph = Qnil;
295 tb->enabled_p = Qnil;
296 tb->help_string = Qnil;
300 tb->pushright = pushright;
302 tb->x = tb->y = tb->width = tb->height = -1;
305 XSETTOOLBAR_BUTTON(retval, tb);
307 /* Let's make sure nothing gets mucked up by the potential call to
308 eval farther down. */
309 GCPRO2(retval, desc);
312 (CONSP(elt[0]) ? elt[0] : symbol_value_in_buffer(elt[0], buffer));
314 /* If this is true we have a blank, otherwise it is an actual
316 if (KEYWORDP(glyphs)) {
320 int len = XVECTOR_LENGTH(desc);
327 for (pos = 0; pos < len; pos += 2) {
328 Lisp_Object key = elt[pos];
329 Lisp_Object val = elt[pos + 1];
331 if (EQ(key, Q_style)) {
334 if (EQ(val, Q2D) || EQ(val, Q2d)) {
335 if (!EQ(Qnil, tb->up_glyph)
336 || !EQ(Qt, tb->disabled_glyph)) {
338 tb->disabled_glyph = Qt;
341 } else if (EQ(val, Q3D) || (EQ(val, Q3d))) {
342 if (!EQ(Qt, tb->up_glyph)
343 || !EQ(Qnil, tb->disabled_glyph)) {
345 tb->disabled_glyph = Qnil;
349 } else if (EQ(key, Q_size)) {
352 if (!EQ(val, tb->down_glyph)) {
353 tb->down_glyph = val;
360 /* The default style is 3D. */
361 if (!EQ(Qt, tb->up_glyph)
362 || !EQ(Qnil, tb->disabled_glyph)) {
364 tb->disabled_glyph = Qnil;
370 /* The default width is set to nil. The device specific
371 code will fill it in at its discretion. */
372 if (!NILP(tb->down_glyph)) {
373 tb->down_glyph = Qnil;
378 /* The rest of these fields are not used by blanks. We make
379 sure they are nulled out in case this button object formerly
380 represented a real button. */
381 if (!NILP(tb->callback)
382 || !NILP(tb->enabled_p)
383 || !NILP(tb->help_string)) {
384 tb->cap_up_glyph = Qnil;
385 tb->cap_down_glyph = Qnil;
386 tb->cap_disabled_glyph = Qnil;
388 tb->enabled_p = Qnil;
389 tb->help_string = Qnil;
398 /* We know that we at least have an up_glyph. Well, no, we
399 don't. The user may have changed the button glyph on us. */
401 if (!EQ(XCAR(glyphs), tb->up_glyph)) {
402 tb->up_glyph = XCAR(glyphs);
405 glyphs = XCDR(glyphs);
409 /* We might have a down_glyph. */
411 if (!EQ(XCAR(glyphs), tb->down_glyph)) {
412 tb->down_glyph = XCAR(glyphs);
415 glyphs = XCDR(glyphs);
417 tb->down_glyph = Qnil;
419 /* We might have a disabled_glyph. */
421 if (!EQ(XCAR(glyphs), tb->disabled_glyph)) {
422 tb->disabled_glyph = XCAR(glyphs);
425 glyphs = XCDR(glyphs);
427 tb->disabled_glyph = Qnil;
429 /* We might have a cap_up_glyph. */
431 if (!EQ(XCAR(glyphs), tb->cap_up_glyph)) {
432 tb->cap_up_glyph = XCAR(glyphs);
435 glyphs = XCDR(glyphs);
437 tb->cap_up_glyph = Qnil;
439 /* We might have a cap_down_glyph. */
441 if (!EQ(XCAR(glyphs), tb->cap_down_glyph)) {
442 tb->cap_down_glyph = XCAR(glyphs);
445 glyphs = XCDR(glyphs);
447 tb->cap_down_glyph = Qnil;
449 /* We might have a cap_disabled_glyph. */
451 if (!EQ(XCAR(glyphs), tb->cap_disabled_glyph)) {
452 tb->cap_disabled_glyph = XCAR(glyphs);
456 tb->cap_disabled_glyph = Qnil;
458 /* Update the callback. */
459 if (!EQ(tb->callback, elt[1])) {
460 tb->callback = elt[1];
461 /* This does not have an impact on the display properties of the
462 button so we do not mark it as dirty if it has changed. */
465 /* Update the enabled field. */
466 if (!EQ(tb->enabled_p, elt[2])) {
467 tb->enabled_p = elt[2];
471 /* We always do the following because if the enabled status is
472 determined by a function its decision may change without us being
473 able to detect it. */
475 int old_enabled = tb->enabled;
477 if (NILP(tb->enabled_p))
479 else if (EQ(tb->enabled_p, Qt))
482 if (NILP(tb->enabled_p)
483 || EQ(tb->enabled_p, Qt))
484 /* short-circuit the common case for speed */
485 tb->enabled = !NILP(tb->enabled_p);
488 eval_in_buffer_trapping_errors
489 ("Error in toolbar enabled-p form",
493 (FRAME_LAST_NONMINIBUF_WINDOW
496 if (UNBOUNDP(result))
497 /* #### if there was an error in the enabled-p
498 form, should we pretend like it's enabled
502 tb->enabled = !NILP(result);
506 if (old_enabled != tb->enabled)
510 /* Update the help echo string. */
511 if (!EQ(tb->help_string, elt[3])) {
512 tb->help_string = elt[3];
513 /* This does not have an impact on the display properties of the
514 button so we do not mark it as dirty if it has changed. */
518 /* If this flag changes, the position is changing for sure unless
519 some very unlikely geometry occurs. */
520 if (tb->pushright != pushright) {
521 tb->pushright = pushright;
525 /* The position and size fields are only manipulated in the
526 device-dependent code. */
531 void mark_frame_toolbar_buttons_dirty(struct frame *f, enum toolbar_pos pos)
533 Lisp_Object button = FRAME_TOOLBAR_BUTTONS(f, pos);
535 while (!NILP(button)) {
536 struct toolbar_button *tb = XTOOLBAR_BUTTON(button);
544 compute_frame_toolbar_buttons(struct frame *f, enum toolbar_pos pos,
547 Lisp_Object buttons, prev_button, first_button;
548 Lisp_Object orig_toolbar = toolbar;
549 int pushright_seen = 0;
550 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
552 first_button = FRAME_TOOLBAR_BUTTONS(f, pos);
553 buttons = prev_button = first_button;
555 /* Yes, we're being paranoid. */
556 GCPRO5(toolbar, buttons, prev_button, first_button, orig_toolbar);
559 /* The output mechanisms will take care of clearing the former
566 signal_simple_error("toolbar description must be a list",
569 /* First synchronize any existing buttons. */
570 while (!NILP(toolbar) && !NILP(buttons)) {
571 struct toolbar_button *tb;
573 if (NILP(XCAR(toolbar))) {
576 ("more than one partition (nil) in toolbar description",
581 tb = XTOOLBAR_BUTTON(buttons);
582 update_toolbar_button(f, tb, XCAR(toolbar),
584 prev_button = buttons;
588 toolbar = XCDR(toolbar);
591 /* If we hit the end of the toolbar, then clean up any excess
592 buttons and return. */
594 if (!NILP(buttons)) {
595 /* If this is the case the only thing we saw was a
597 if (EQ(buttons, first_button)) {
601 XTOOLBAR_BUTTON(prev_button)->next = Qnil;
607 /* At this point there are more buttons on the toolbar than we
608 actually have in existence. */
609 while (!NILP(toolbar)) {
610 Lisp_Object new_button;
612 if (NILP(XCAR(toolbar))) {
615 ("more than one partition (nil) in toolbar description",
621 update_toolbar_button(f, NULL, XCAR(toolbar),
624 if (NILP(first_button)) {
625 first_button = prev_button = new_button;
627 XTOOLBAR_BUTTON(prev_button)->next = new_button;
628 prev_button = new_button;
632 toolbar = XCDR(toolbar);
639 static void set_frame_toolbar(struct frame *f, enum toolbar_pos pos)
641 struct window *w = XWINDOW(FRAME_LAST_NONMINIBUF_WINDOW(f));
642 Lisp_Object toolbar = w->toolbar[pos];
643 f->toolbar_buttons[pos] = (FRAME_REAL_TOOLBAR_VISIBLE(f, pos)
644 ? compute_frame_toolbar_buttons(f, pos,
649 static void compute_frame_toolbars_data(struct frame *f)
651 set_frame_toolbar(f, TOP_TOOLBAR);
652 set_frame_toolbar(f, BOTTOM_TOOLBAR);
653 set_frame_toolbar(f, LEFT_TOOLBAR);
654 set_frame_toolbar(f, RIGHT_TOOLBAR);
657 /* Update the toolbar geometry separately from actually displaying the
658 toolbar. This is necessary because both the gutter and the toolbar
659 are competing for redisplay cycles and, unfortunately, gutter
660 updates happen late in the game. Firstly they are done inside of
661 redisplay proper and secondly subcontrols may not get moved until
662 the next screen refresh. Only after subcontrols have been moved to
663 their final destinations can we be certain of updating the
664 toolbar. Under X this probably is exacerbated by the toolbar button
665 dirty flags which prevent updates happening when they possibly
667 void update_frame_toolbars_geometry(struct frame *f)
669 struct device *d = XDEVICE(f->device);
671 if (DEVICE_SUPPORTS_TOOLBARS_P(d)
672 && (f->toolbar_changed
673 || f->frame_layout_changed || f->frame_changed || f->clear)) {
676 /* We're not officially "in redisplay", so we still have a
677 chance to re-layout toolbars and windows. This is done here,
678 because toolbar is the only thing which currently might
679 necessitate this layout, as it is outside any windows. We
680 take care not to change size if toolbar geometry is really
681 unchanged, as it will hose windows whose pixsizes are not
682 multiple of character sizes. */
684 for (pos = 0; pos < 4; pos++)
685 if (FRAME_REAL_TOOLBAR_SIZE(f, pos)
686 != FRAME_CURRENT_TOOLBAR_SIZE(f, pos)) {
688 pixel_to_char_size(f, FRAME_PIXWIDTH(f),
689 FRAME_PIXHEIGHT(f), &width,
691 change_frame_size(f, height, width, 0);
692 MARK_FRAME_LAYOUT_CHANGED(f);
696 for (pos = 0; pos < 4; pos++) {
697 f->current_toolbar_size[pos] =
698 FRAME_REAL_TOOLBAR_SIZE(f, pos);
701 /* Removed the check for the minibuffer here. We handle this
702 more correctly now by consistently using
703 FRAME_LAST_NONMINIBUF_WINDOW instead of FRAME_SELECTED_WINDOW
704 throughout the toolbar code. */
705 compute_frame_toolbars_data(f);
707 /* Clear the previous toolbar locations. If we do it later
708 (after redisplay) we end up clearing what we have just
710 MAYBE_DEVMETH(d, clear_frame_toolbars, (f));
714 /* Actually redisplay the toolbar buttons. */
715 void update_frame_toolbars(struct frame *f)
717 struct device *d = XDEVICE(f->device);
719 if (DEVICE_SUPPORTS_TOOLBARS_P(d)
720 && (f->toolbar_changed
721 || f->frame_layout_changed || f->frame_changed || f->clear)) {
722 DEVMETH(d, output_frame_toolbars, (f));
725 f->toolbar_changed = 0;
728 void init_frame_toolbars(struct frame *f)
730 struct device *d = XDEVICE(f->device);
732 if (DEVICE_SUPPORTS_TOOLBARS_P(d)) {
736 compute_frame_toolbars_data(f);
738 call_critical_lisp_code(XDEVICE(FRAME_DEVICE(f)),
739 Qinit_toolbar_from_resources, frame);
740 MAYBE_DEVMETH(d, initialize_frame_toolbars, (f));
742 /* We are here as far in frame creation so cached specifiers are
743 already recomputed, and possibly modified by resource
744 initialization. Remember current toolbar geometry so next
745 redisplay will not needlessly relayout toolbars. */
746 for (pos = 0; pos < 4; pos++)
747 f->current_toolbar_size[pos] =
748 FRAME_REAL_TOOLBAR_SIZE(f, pos);
752 void init_device_toolbars(struct device *d)
756 XSETDEVICE(device, d);
757 if (DEVICE_SUPPORTS_TOOLBARS_P(d))
758 call_critical_lisp_code(d,
759 Qinit_toolbar_from_resources, device);
762 void init_global_toolbars(struct device *d)
764 if (DEVICE_SUPPORTS_TOOLBARS_P(d))
765 call_critical_lisp_code(d,
766 Qinit_toolbar_from_resources, Qglobal);
769 void free_frame_toolbars(struct frame *f)
771 /* If we had directly allocated any memory for the toolbars instead
772 of using all Lisp_Objects this is where we would now free it. */
774 MAYBE_FRAMEMETH(f, free_frame_toolbars, (f));
778 get_toolbar_coords(struct frame *f, enum toolbar_pos pos, int *x, int *y,
779 int *width, int *height, int *vert, int for_layout)
781 int visible_top_toolbar_height, visible_bottom_toolbar_height;
782 int adjust = (for_layout ? 1 : 0);
784 /* The top and bottom toolbars take precedence over the left and
786 visible_top_toolbar_height = (FRAME_REAL_TOP_TOOLBAR_VISIBLE(f)
787 ? FRAME_REAL_TOP_TOOLBAR_HEIGHT(f) +
788 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH(f)
790 visible_bottom_toolbar_height = (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE(f)
791 ? FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT(f) +
793 FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH
797 /* We adjust the width and height by one to give us a narrow border
798 at the outside edges. However, when we are simply determining
799 toolbar location we don't want to do that. */
804 *y = 0; /* #### should be 1 if no menubar */
805 *width = FRAME_PIXWIDTH(f) - 2;
806 *height = FRAME_REAL_TOP_TOOLBAR_HEIGHT(f) +
807 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH(f) - adjust;
812 *y = FRAME_PIXHEIGHT(f) - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT(f) -
813 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH(f);
814 *width = FRAME_PIXWIDTH(f) - 2;
815 *height = FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT(f) +
816 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH(f) - adjust;
821 *y = visible_top_toolbar_height;
822 *width = FRAME_REAL_LEFT_TOOLBAR_WIDTH(f) +
823 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH(f) - adjust;
824 *height = (FRAME_PIXHEIGHT(f) - visible_top_toolbar_height -
825 visible_bottom_toolbar_height - 1);
829 *x = FRAME_PIXWIDTH(f) - FRAME_REAL_RIGHT_TOOLBAR_WIDTH(f) -
830 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH(f);
831 *y = visible_top_toolbar_height;
832 *width = FRAME_REAL_RIGHT_TOOLBAR_WIDTH(f) +
833 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH(f) - adjust;
834 *height = (FRAME_PIXHEIGHT(f) - visible_top_toolbar_height -
835 visible_bottom_toolbar_height);
843 #define CHECK_TOOLBAR(pos) do { \
844 if (FRAME_REAL_##pos##_VISIBLE (f)) \
846 int x, y, width, height, vert; \
848 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 0); \
849 if ((x_coord >= x) && (x_coord < (x + width))) \
851 if ((y_coord >= y) && (y_coord < (y + height))) \
852 return FRAME_TOOLBAR_BUTTONS (f, pos); \
858 toolbar_buttons_at_pixpos(struct frame *f, int x_coord, int y_coord)
860 CHECK_TOOLBAR(TOP_TOOLBAR);
861 CHECK_TOOLBAR(BOTTOM_TOOLBAR);
862 CHECK_TOOLBAR(LEFT_TOOLBAR);
863 CHECK_TOOLBAR(RIGHT_TOOLBAR);
870 /* The device dependent code actually does the work of positioning the
871 buttons, but we are free to access that information at this
873 Lisp_Object toolbar_button_at_pixpos(struct frame * f, int x_coord, int y_coord)
875 Lisp_Object buttons = toolbar_buttons_at_pixpos(f, x_coord, y_coord);
877 while (!NILP(buttons)) {
878 struct toolbar_button *tb = XTOOLBAR_BUTTON(buttons);
880 if ((x_coord >= tb->x) && (x_coord < (tb->x + tb->width))) {
881 if ((y_coord >= tb->y)
882 && (y_coord < (tb->y + tb->height))) {
883 /* If we are over a blank, return nil. */
894 /* We are not over a toolbar or we are over a blank in the toolbar. */
898 /************************************************************************/
899 /* Toolbar specifier type */
900 /************************************************************************/
902 DEFINE_SPECIFIER_TYPE(toolbar);
904 #define CTB_ERROR(msg) do { \
905 maybe_signal_simple_error (msg, button, Qtoolbar, errb); \
906 RETURN_SANS_WARNINGS Qnil; \
909 /* Returns Q_style if key was :style, Qt if ok otherwise, Qnil if error. */
911 check_toolbar_button_keywords(Lisp_Object button, Lisp_Object key,
912 Lisp_Object val, Error_behavior errb)
914 if (!KEYWORDP(key)) {
915 maybe_signal_simple_error_2("Not a keyword", key, button,
920 if (EQ(key, Q_style)) {
925 CTB_ERROR("Unrecognized toolbar blank style");
928 } else if (EQ(key, Q_size)) {
930 CTB_ERROR("invalid toolbar blank size");
932 CTB_ERROR("invalid toolbar blank keyword");
938 /* toolbar button spec is [pixmap-pair function enabled-p help]
939 or [:style 2d-or-3d :size width-or-height] */
941 DEFUN("check-toolbar-button-syntax", Fcheck_toolbar_button_syntax, 1, 2, 0, /*
942 Verify the syntax of entry BUTTON in a toolbar description list.
943 If you want to verify the syntax of a toolbar description list as a
944 whole, use `check-valid-instantiator' with a specifier type of 'toolbar.
948 Lisp_Object *elt, glyphs, value;
950 Error_behavior errb = decode_error_behavior_flag(noerror);
952 if (!VECTORP(button))
953 CTB_ERROR("toolbar button descriptors must be vectors");
954 elt = XVECTOR_DATA(button);
956 if (XVECTOR_LENGTH(button) == 2) {
957 if (!EQ(Q_style, check_toolbar_button_keywords(button, elt[0],
959 CTB_ERROR("must specify toolbar blank style");
964 if (XVECTOR_LENGTH(button) != 4)
965 CTB_ERROR("toolbar button descriptors must be 2 or 4 long");
967 /* The first element must be a list of glyphs of length 1-6. The
968 first entry is the pixmap for the up state, the second for the
969 down state, the third for the disabled state, the fourth for the
970 captioned up state, the fifth for the captioned down state and
971 the sixth for the captioned disabled state. Only the up state is
973 if (!CONSP(elt[0])) {
974 /* We can't check the buffer-local here because we don't know
975 which buffer to check in. #### I think this is a bad thing.
976 See if we can't get enough information to this function so
979 #### Wrong. We shouldn't be checking the value at all here.
980 The user might set or change the value at any time. */
981 value = Fsymbol_value(elt[0]);
984 if (KEYWORDP(elt[0])) {
989 check_toolbar_button_keywords(button,
997 check_toolbar_button_keywords(button,
1005 ("must specify toolbar blank style");
1006 else if (EQ(elt[0], elt[2]))
1008 ("duplicate keywords in toolbar button blank description");
1013 ("first element of button must be a list (of glyphs)");
1018 len = XINT(Flength(value));
1021 ("toolbar button glyph list must have at least 1 entry");
1025 ("toolbar button glyph list can have at most 6 entries");
1028 while (!NILP(glyphs)) {
1029 if (!GLYPHP(XCAR(glyphs))) {
1030 /* We allow nil for the down and disabled glyphs but not for
1032 if (EQ(glyphs, value) || !NILP(XCAR(glyphs))) {
1034 ("all elements of toolbar button glyph list must be glyphs.");
1037 glyphs = XCDR(glyphs);
1040 /* The second element is the function to run when the button is
1041 activated. We do not do any checking on it because it is legal
1042 for the function to not be defined until after the toolbar is.
1043 It is the user's problem to get this right.
1045 The third element is either a boolean indicating the enabled
1046 status or a function used to determine it. Again, it is the
1047 user's problem if this is wrong.
1049 The fourth element, if not nil, must be a string which will be
1050 displayed as the help echo. */
1052 /* #### This should be allowed to be a function returning a string
1053 as well as just a string. */
1054 if (!NILP(elt[3]) && !STRINGP(elt[3]))
1055 CTB_ERROR("toolbar button help echo string must be a string");
1062 static void toolbar_validate(Lisp_Object instantiator)
1064 int pushright_seen = 0;
1067 if (NILP(instantiator))
1070 if (!CONSP(instantiator))
1071 signal_simple_error("Toolbar spec must be list or nil",
1074 for (rest = instantiator; !NILP(rest); rest = XCDR(rest)) {
1076 signal_simple_error("Bad list in toolbar spec",
1079 if (NILP(XCAR(rest))) {
1082 ("More than one partition (nil) in instantiator description");
1086 Fcheck_toolbar_button_syntax(XCAR(rest), Qnil);
1090 static void toolbar_after_change(Lisp_Object specifier, Lisp_Object locale)
1092 /* #### This is overkill. I really need to rethink the after-change
1093 functions to make them easier to use. */
1094 MARK_TOOLBAR_CHANGED;
1097 DEFUN("toolbar-specifier-p", Ftoolbar_specifier_p, 1, 1, 0, /*
1098 Return non-nil if OBJECT is a toolbar specifier.
1100 See `make-toolbar-specifier' for a description of possible toolbar
1105 return TOOLBAR_SPECIFIERP(object) ? Qt : Qnil;
1109 Helper for invalidating the real specifier when default
1110 specifier caching changes
1112 static void recompute_overlaying_specifier(Lisp_Object real_one[4])
1114 enum toolbar_pos pos =
1115 decode_toolbar_position(Vdefault_toolbar_position);
1116 Fset_specifier_dirty_flag(real_one[pos]);
1120 toolbar_specs_changed(Lisp_Object specifier, struct window *w,
1123 /* This could be smarter but I doubt that it would make any
1124 noticeable difference given the infrequency with which this is
1125 probably going to be called.
1127 MARK_TOOLBAR_CHANGED;
1131 default_toolbar_specs_changed(Lisp_Object specifier, struct window *w,
1134 recompute_overlaying_specifier(Vtoolbar);
1138 default_toolbar_size_changed_in_frame(Lisp_Object specifier, struct frame *f,
1141 recompute_overlaying_specifier(Vtoolbar_size);
1145 default_toolbar_border_width_changed_in_frame(Lisp_Object specifier,
1149 recompute_overlaying_specifier(Vtoolbar_border_width);
1153 default_toolbar_visible_p_changed_in_frame(Lisp_Object specifier,
1154 struct frame *f, Lisp_Object oldval)
1156 recompute_overlaying_specifier(Vtoolbar_visible_p);
1160 toolbar_geometry_changed_in_window(Lisp_Object specifier, struct window *w,
1163 MARK_TOOLBAR_CHANGED;
1164 MARK_WINDOWS_CHANGED(w);
1168 default_toolbar_size_changed_in_window(Lisp_Object specifier, struct window *w,
1171 recompute_overlaying_specifier(Vtoolbar_size);
1175 default_toolbar_border_width_changed_in_window(Lisp_Object specifier,
1179 recompute_overlaying_specifier(Vtoolbar_border_width);
1183 default_toolbar_visible_p_changed_in_window(Lisp_Object specifier,
1187 recompute_overlaying_specifier(Vtoolbar_visible_p);
1191 toolbar_buttons_captioned_p_changed(Lisp_Object specifier, struct window *w,
1194 /* This could be smarter but I doubt that it would make any
1195 noticeable difference given the infrequency with which this is
1196 probably going to be called. */
1197 MARK_TOOLBAR_CHANGED;
1200 void syms_of_toolbar(void)
1202 INIT_LRECORD_IMPLEMENTATION(toolbar_button);
1204 defsymbol(&Qtoolbar_buttonp, "toolbar-button-p");
1205 defsymbol(&Q2D, "2D");
1206 defsymbol(&Q3D, "3D");
1207 defsymbol(&Q2d, "2d");
1208 defsymbol(&Q3d, "3d");
1209 defsymbol(&Q_size, ":size");
1210 Fset(Q_size, Q_size);
1212 defsymbol(&Qinit_toolbar_from_resources, "init-toolbar-from-resources");
1213 DEFSUBR(Ftoolbar_button_p);
1214 DEFSUBR(Ftoolbar_button_callback);
1215 DEFSUBR(Ftoolbar_button_help_string);
1216 DEFSUBR(Ftoolbar_button_enabled_p);
1217 DEFSUBR(Fset_toolbar_button_down_flag);
1218 DEFSUBR(Fcheck_toolbar_button_syntax);
1219 DEFSUBR(Fset_default_toolbar_position);
1220 DEFSUBR(Fdefault_toolbar_position);
1221 DEFSUBR(Ftoolbar_specifier_p);
1224 void vars_of_toolbar(void)
1226 staticpro(&Vdefault_toolbar_position);
1227 Vdefault_toolbar_position = Qtop;
1229 #ifdef HAVE_WINDOW_SYSTEM
1234 void specifier_type_create_toolbar(void)
1236 INITIALIZE_SPECIFIER_TYPE(toolbar, "toolbar", "toolbar-specifier-p");
1238 SPECIFIER_HAS_METHOD(toolbar, validate);
1239 SPECIFIER_HAS_METHOD(toolbar, after_change);
1242 void reinit_specifier_type_create_toolbar(void)
1244 REINITIALIZE_SPECIFIER_TYPE(toolbar);
1247 void specifier_vars_of_toolbar(void)
1251 DEFVAR_SPECIFIER("default-toolbar", &Vdefault_toolbar /*
1252 Specifier for a fallback toolbar.
1253 Use `set-specifier' to change this.
1255 The position of this toolbar is specified in the function
1256 `default-toolbar-position'. If the corresponding position-specific
1257 toolbar (e.g. `top-toolbar' if `default-toolbar-position' is 'top)
1258 does not specify a toolbar in a particular domain (usually a window),
1259 then the value of `default-toolbar' in that domain, if any, will be
1262 Note that the toolbar at any particular position will not be
1263 displayed unless its visibility flag is true and its thickness
1264 \(width or height, depending on orientation) is non-zero. The
1265 visibility is controlled by the specifiers `top-toolbar-visible-p',
1266 `bottom-toolbar-visible-p', `left-toolbar-visible-p', and
1267 `right-toolbar-visible-p', and the thickness is controlled by the
1268 specifiers `top-toolbar-height', `bottom-toolbar-height',
1269 `left-toolbar-width', and `right-toolbar-width'.
1271 Note that one of the four visibility specifiers inherits from
1272 `default-toolbar-visibility' and one of the four thickness
1273 specifiers inherits from either `default-toolbar-width' or
1274 `default-toolbar-height' (depending on orientation), just
1275 like for the toolbar description specifiers (e.g. `top-toolbar')
1278 Therefore, if you are setting `default-toolbar', you should control
1279 the visibility and thickness using `default-toolbar-visible-p',
1280 `default-toolbar-width', and `default-toolbar-height', rather than
1281 using position-specific specifiers. That way, you will get sane
1282 behavior if the user changes the default toolbar position.
1284 The format of the instantiator for a toolbar is a list of
1285 toolbar-button-descriptors. Each toolbar-button-descriptor
1286 is a vector in one of the following formats:
1288 [GLYPH-LIST FUNCTION ENABLED-P HELP] or
1289 [:style 2D-OR-3D] or
1290 [:style 2D-OR-3D :size WIDTH-OR-HEIGHT] or
1291 [:size WIDTH-OR-HEIGHT :style 2D-OR-3D]
1293 Optionally, one of the toolbar-button-descriptors may be nil
1294 instead of a vector; this signifies the division between
1295 the toolbar buttons that are to be displayed flush-left,
1296 and the buttons to be displayed flush-right.
1298 The first vector format above specifies a normal toolbar button;
1299 the others specify blank areas in the toolbar.
1301 For the first vector format:
1303 -- GLYPH-LIST should be a list of one to six glyphs (as created by
1304 `make-glyph') or a symbol whose value is such a list. The first
1305 glyph, which must be provided, is the glyph used to display the
1306 toolbar button when it is in the "up" (not pressed) state. The
1307 optional second glyph is for displaying the button when it is in
1308 the "down" (pressed) state. The optional third glyph is for when
1309 the button is disabled. The optional fourth, fifth and sixth glyphs
1310 are used to specify captioned versions for the up, down and disabled
1311 states respectively. The function `toolbar-make-button-list' is
1312 useful in creating these glyph lists. The specifier variable
1313 `toolbar-buttons-captioned-p' controls which glyphs are actually used.
1315 -- Even if you do not provide separate down-state and disabled-state
1316 glyphs, the user will still get visual feedback to indicate which
1317 state the button is in. Buttons in the up-state are displayed
1318 with a shadowed border that gives a raised appearance to the
1319 button. Buttons in the down-state are displayed with shadows that
1320 give a recessed appearance. Buttons in the disabled state are
1321 displayed with no shadows, giving a 2-d effect.
1323 -- If some of the toolbar glyphs are not provided, they inherit as follows:
1327 DISABLED: disabled -> up
1328 CAP-UP: cap-up -> up
1329 CAP-DOWN: cap-down -> cap-up -> down -> up
1330 CAP-DISABLED: cap-disabled -> cap-up -> disabled -> up
1332 -- The second element FUNCTION is a function to be called when the
1333 toolbar button is activated (i.e. when the mouse is released over
1334 the toolbar button, if the press occurred in the toolbar). It
1335 can be any form accepted by `call-interactively', since this is
1338 -- The third element ENABLED-P specifies whether the toolbar button
1339 is enabled (disabled buttons do nothing when they are activated,
1340 and are displayed differently; see above). It should be either
1341 a boolean or a form that evaluates to a boolean.
1343 -- The fourth element HELP, if non-nil, should be a string. This
1344 string is displayed in the echo area when the mouse passes over
1347 For the other vector formats (specifying blank areas of the toolbar):
1349 -- 2D-OR-3D should be one of the symbols '2d or '3d, indicating
1350 whether the area is displayed with shadows (giving it a raised,
1351 3-d appearance) or without shadows (giving it a flat appearance).
1353 -- WIDTH-OR-HEIGHT specifies the length, in pixels, of the blank
1354 area. If omitted, it defaults to a device-specific value
1355 (8 pixels for X devices).
1358 Vdefault_toolbar = Fmake_specifier(Qtoolbar);
1359 /* #### It would be even nicer if the specifier caching
1360 automatically knew about specifier fallbacks, so we didn't
1361 have to do it ourselves. */
1362 set_specifier_caching(Vdefault_toolbar,
1363 offsetof(struct window, default_toolbar),
1364 default_toolbar_specs_changed, 0, 0, 0);
1366 DEFVAR_SPECIFIER("top-toolbar", &Vtoolbar[TOP_TOOLBAR] /*
1367 Specifier for the toolbar at the top of the frame.
1368 Use `set-specifier' to change this.
1369 See `default-toolbar' for a description of a valid toolbar instantiator.
1371 Vtoolbar[TOP_TOOLBAR] = Fmake_specifier(Qtoolbar);
1372 set_specifier_caching(Vtoolbar[TOP_TOOLBAR],
1373 offsetof(struct window, toolbar[TOP_TOOLBAR]),
1374 toolbar_specs_changed, 0, 0, 0);
1376 DEFVAR_SPECIFIER("bottom-toolbar", &Vtoolbar[BOTTOM_TOOLBAR] /*
1377 Specifier for the toolbar at the bottom of the frame.
1378 Use `set-specifier' to change this.
1379 See `default-toolbar' for a description of a valid toolbar instantiator.
1381 Note that, unless the `default-toolbar-position' is `bottom', by
1382 default the height of the bottom toolbar (controlled by
1383 `bottom-toolbar-height') is 0; thus, a bottom toolbar will not be
1384 displayed even if you provide a value for `bottom-toolbar'.
1386 Vtoolbar[BOTTOM_TOOLBAR] = Fmake_specifier(Qtoolbar);
1387 set_specifier_caching(Vtoolbar[BOTTOM_TOOLBAR],
1388 offsetof(struct window, toolbar[BOTTOM_TOOLBAR]),
1389 toolbar_specs_changed, 0, 0, 0);
1391 DEFVAR_SPECIFIER("left-toolbar", &Vtoolbar[LEFT_TOOLBAR] /*
1392 Specifier for the toolbar at the left edge of the frame.
1393 Use `set-specifier' to change this.
1394 See `default-toolbar' for a description of a valid toolbar instantiator.
1396 Note that, unless the `default-toolbar-position' is `left', by
1397 default the height of the left toolbar (controlled by
1398 `left-toolbar-width') is 0; thus, a left toolbar will not be
1399 displayed even if you provide a value for `left-toolbar'.
1401 Vtoolbar[LEFT_TOOLBAR] = Fmake_specifier(Qtoolbar);
1402 set_specifier_caching(Vtoolbar[LEFT_TOOLBAR],
1403 offsetof(struct window, toolbar[LEFT_TOOLBAR]),
1404 toolbar_specs_changed, 0, 0, 0);
1406 DEFVAR_SPECIFIER("right-toolbar", &Vtoolbar[RIGHT_TOOLBAR] /*
1407 Specifier for the toolbar at the right edge of the frame.
1408 Use `set-specifier' to change this.
1409 See `default-toolbar' for a description of a valid toolbar instantiator.
1411 Note that, unless the `default-toolbar-position' is `right', by
1412 default the height of the right toolbar (controlled by
1413 `right-toolbar-width') is 0; thus, a right toolbar will not be
1414 displayed even if you provide a value for `right-toolbar'.
1416 Vtoolbar[RIGHT_TOOLBAR] = Fmake_specifier(Qtoolbar);
1417 set_specifier_caching(Vtoolbar[RIGHT_TOOLBAR],
1418 offsetof(struct window, toolbar[RIGHT_TOOLBAR]),
1419 toolbar_specs_changed, 0, 0, 0);
1421 /* initially, top inherits from default; this can be
1422 changed with `set-default-toolbar-position'. */
1423 fb = list1(Fcons(Qnil, Qnil));
1424 set_specifier_fallback(Vdefault_toolbar, fb);
1425 set_specifier_fallback(Vtoolbar[TOP_TOOLBAR], Vdefault_toolbar);
1426 set_specifier_fallback(Vtoolbar[BOTTOM_TOOLBAR], fb);
1427 set_specifier_fallback(Vtoolbar[LEFT_TOOLBAR], fb);
1428 set_specifier_fallback(Vtoolbar[RIGHT_TOOLBAR], fb);
1430 DEFVAR_SPECIFIER("default-toolbar-height", &Vdefault_toolbar_height /*
1431 *Height of the default toolbar, if it's oriented horizontally.
1432 This is a specifier; use `set-specifier' to change it.
1434 The position of the default toolbar is specified by the function
1435 `set-default-toolbar-position'. If the corresponding position-specific
1436 toolbar thickness specifier (e.g. `top-toolbar-height' if
1437 `default-toolbar-position' is 'top) does not specify a thickness in a
1438 particular domain (a window or a frame), then the value of
1439 `default-toolbar-height' or `default-toolbar-width' (depending on the
1440 toolbar orientation) in that domain, if any, will be used instead.
1442 Note that `default-toolbar-height' is only used when
1443 `default-toolbar-position' is 'top or 'bottom, and `default-toolbar-width'
1444 is only used when `default-toolbar-position' is 'left or 'right.
1446 Note that all of the position-specific toolbar thickness specifiers
1447 have a fallback value of zero when they do not correspond to the
1448 default toolbar. Therefore, you will have to set a non-zero thickness
1449 value if you want a position-specific toolbar to be displayed.
1451 Internally, toolbar thickness specifiers are instantiated in both
1452 window and frame domains, for different purposes. The value in the
1453 domain of a frame's selected window specifies the actual toolbar
1454 thickness that you will see in that frame. The value in the domain of
1455 a frame itself specifies the toolbar thickness that is used in frame
1456 geometry calculations.
1458 Thus, for example, if you set the frame width to 80 characters and the
1459 left toolbar width for that frame to 68 pixels, then the frame will
1460 be sized to fit 80 characters plus a 68-pixel left toolbar. If you
1461 then set the left toolbar width to 0 for a particular buffer (or if
1462 that buffer does not specify a left toolbar or has a nil value
1463 specified for `left-toolbar-visible-p'), you will find that, when
1464 that buffer is displayed in the selected window, the window will have
1465 a width of 86 or 87 characters -- the frame is sized for a 68-pixel
1466 left toolbar but the selected window specifies that the left toolbar
1467 is not visible, so it is expanded to take up the slack.
1469 Vdefault_toolbar_height = Fmake_specifier(Qnatnum);
1470 set_specifier_caching(Vdefault_toolbar_height,
1471 offsetof(struct window, default_toolbar_height),
1472 default_toolbar_size_changed_in_window,
1473 offsetof(struct frame, default_toolbar_height),
1474 default_toolbar_size_changed_in_frame, 0);
1476 DEFVAR_SPECIFIER("default-toolbar-width", &Vdefault_toolbar_width /*
1477 *Width of the default toolbar, if it's oriented vertically.
1478 This is a specifier; use `set-specifier' to change it.
1480 See `default-toolbar-height' for more information.
1482 Vdefault_toolbar_width = Fmake_specifier(Qnatnum);
1483 set_specifier_caching(Vdefault_toolbar_width,
1484 offsetof(struct window, default_toolbar_width),
1485 default_toolbar_size_changed_in_window,
1486 offsetof(struct frame, default_toolbar_width),
1487 default_toolbar_size_changed_in_frame, 0);
1489 DEFVAR_SPECIFIER("top-toolbar-height", &Vtoolbar_size[TOP_TOOLBAR] /*
1490 *Height of the top toolbar.
1491 This is a specifier; use `set-specifier' to change it.
1493 See `default-toolbar-height' for more information.
1495 Vtoolbar_size[TOP_TOOLBAR] = Fmake_specifier(Qnatnum);
1496 set_specifier_caching(Vtoolbar_size[TOP_TOOLBAR],
1497 offsetof(struct window,
1498 toolbar_size[TOP_TOOLBAR]),
1499 toolbar_geometry_changed_in_window,
1500 offsetof(struct frame, toolbar_size[TOP_TOOLBAR]),
1501 frame_size_slipped, 0);
1503 DEFVAR_SPECIFIER("bottom-toolbar-height", &Vtoolbar_size[BOTTOM_TOOLBAR] /*
1504 *Height of the bottom toolbar.
1505 This is a specifier; use `set-specifier' to change it.
1507 See `default-toolbar-height' for more information.
1509 Vtoolbar_size[BOTTOM_TOOLBAR] = Fmake_specifier(Qnatnum);
1510 set_specifier_caching(Vtoolbar_size[BOTTOM_TOOLBAR],
1511 offsetof(struct window,
1512 toolbar_size[BOTTOM_TOOLBAR]),
1513 toolbar_geometry_changed_in_window,
1514 offsetof(struct frame,
1515 toolbar_size[BOTTOM_TOOLBAR]),
1516 frame_size_slipped, 0);
1518 DEFVAR_SPECIFIER("left-toolbar-width", &Vtoolbar_size[LEFT_TOOLBAR] /*
1519 *Width of left toolbar.
1520 This is a specifier; use `set-specifier' to change it.
1522 See `default-toolbar-height' for more information.
1524 Vtoolbar_size[LEFT_TOOLBAR] = Fmake_specifier(Qnatnum);
1525 set_specifier_caching(Vtoolbar_size[LEFT_TOOLBAR],
1526 offsetof(struct window,
1527 toolbar_size[LEFT_TOOLBAR]),
1528 toolbar_geometry_changed_in_window,
1529 offsetof(struct frame,
1530 toolbar_size[LEFT_TOOLBAR]),
1531 frame_size_slipped, 0);
1533 DEFVAR_SPECIFIER("right-toolbar-width", &Vtoolbar_size[RIGHT_TOOLBAR] /*
1534 *Width of right toolbar.
1535 This is a specifier; use `set-specifier' to change it.
1537 See `default-toolbar-height' for more information.
1539 Vtoolbar_size[RIGHT_TOOLBAR] = Fmake_specifier(Qnatnum);
1540 set_specifier_caching(Vtoolbar_size[RIGHT_TOOLBAR],
1541 offsetof(struct window,
1542 toolbar_size[RIGHT_TOOLBAR]),
1543 toolbar_geometry_changed_in_window,
1544 offsetof(struct frame,
1545 toolbar_size[RIGHT_TOOLBAR]),
1546 frame_size_slipped, 0);
1550 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
1552 #ifdef HAVE_X_WINDOWS
1553 fb = Fcons(Fcons(list1(Qx), make_int(DEFAULT_TOOLBAR_HEIGHT)), fb);
1556 set_specifier_fallback(Vdefault_toolbar_height, fb);
1560 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
1562 #ifdef HAVE_X_WINDOWS
1563 fb = Fcons(Fcons(list1(Qx), make_int(DEFAULT_TOOLBAR_WIDTH)), fb);
1566 set_specifier_fallback(Vdefault_toolbar_width, fb);
1568 set_specifier_fallback(Vtoolbar_size[TOP_TOOLBAR],
1569 Vdefault_toolbar_height);
1570 fb = list1(Fcons(Qnil, Qzero));
1571 set_specifier_fallback(Vtoolbar_size[BOTTOM_TOOLBAR], fb);
1572 set_specifier_fallback(Vtoolbar_size[LEFT_TOOLBAR], fb);
1573 set_specifier_fallback(Vtoolbar_size[RIGHT_TOOLBAR], fb);
1575 DEFVAR_SPECIFIER("default-toolbar-border-width", &Vdefault_toolbar_border_width /*
1576 *Width of the border around the default toolbar.
1577 This is a specifier; use `set-specifier' to change it.
1579 The position of the default toolbar is specified by the function
1580 `set-default-toolbar-position'. If the corresponding position-specific
1581 toolbar border width specifier (e.g. `top-toolbar-border-width' if
1582 `default-toolbar-position' is 'top) does not specify a border width in a
1583 particular domain (a window or a frame), then the value of
1584 `default-toolbar-border-width' in that domain, if any, will be used
1587 Internally, toolbar border width specifiers are instantiated in both
1588 window and frame domains, for different purposes. The value in the
1589 domain of a frame's selected window specifies the actual toolbar border
1590 width that you will see in that frame. The value in the domain of a
1591 frame itself specifies the toolbar border width that is used in frame
1592 geometry calculations. Changing the border width value in the frame
1593 domain will result in a size change in the frame itself, while changing
1594 the value in a window domain will not.
1596 Vdefault_toolbar_border_width = Fmake_specifier(Qnatnum);
1597 set_specifier_caching(Vdefault_toolbar_border_width,
1598 offsetof(struct window,
1599 default_toolbar_border_width),
1600 default_toolbar_border_width_changed_in_window,
1601 offsetof(struct frame,
1602 default_toolbar_border_width),
1603 default_toolbar_border_width_changed_in_frame, 0);
1605 DEFVAR_SPECIFIER("top-toolbar-border-width", &Vtoolbar_border_width[TOP_TOOLBAR] /*
1606 *Border width of the top toolbar.
1607 This is a specifier; use `set-specifier' to change it.
1609 See `default-toolbar-height' for more information.
1611 Vtoolbar_border_width[TOP_TOOLBAR] = Fmake_specifier(Qnatnum);
1612 set_specifier_caching(Vtoolbar_border_width[TOP_TOOLBAR],
1613 offsetof(struct window,
1614 toolbar_border_width[TOP_TOOLBAR]),
1615 toolbar_geometry_changed_in_window,
1616 offsetof(struct frame,
1617 toolbar_border_width[TOP_TOOLBAR]),
1618 frame_size_slipped, 0);
1620 DEFVAR_SPECIFIER("bottom-toolbar-border-width", &Vtoolbar_border_width[BOTTOM_TOOLBAR] /*
1621 *Border width of the bottom toolbar.
1622 This is a specifier; use `set-specifier' to change it.
1624 See `default-toolbar-height' for more information.
1626 Vtoolbar_border_width[BOTTOM_TOOLBAR] = Fmake_specifier(Qnatnum);
1627 set_specifier_caching(Vtoolbar_border_width[BOTTOM_TOOLBAR],
1628 offsetof(struct window,
1629 toolbar_border_width[BOTTOM_TOOLBAR]),
1630 toolbar_geometry_changed_in_window,
1631 offsetof(struct frame,
1632 toolbar_border_width[BOTTOM_TOOLBAR]),
1633 frame_size_slipped, 0);
1635 DEFVAR_SPECIFIER("left-toolbar-border-width", &Vtoolbar_border_width[LEFT_TOOLBAR] /*
1636 *Border width of left toolbar.
1637 This is a specifier; use `set-specifier' to change it.
1639 See `default-toolbar-height' for more information.
1641 Vtoolbar_border_width[LEFT_TOOLBAR] = Fmake_specifier(Qnatnum);
1642 set_specifier_caching(Vtoolbar_border_width[LEFT_TOOLBAR],
1643 offsetof(struct window,
1644 toolbar_border_width[LEFT_TOOLBAR]),
1645 toolbar_geometry_changed_in_window,
1646 offsetof(struct frame,
1647 toolbar_border_width[LEFT_TOOLBAR]),
1648 frame_size_slipped, 0);
1650 DEFVAR_SPECIFIER("right-toolbar-border-width", &Vtoolbar_border_width[RIGHT_TOOLBAR] /*
1651 *Border width of right toolbar.
1652 This is a specifier; use `set-specifier' to change it.
1654 See `default-toolbar-height' for more information.
1656 Vtoolbar_border_width[RIGHT_TOOLBAR] = Fmake_specifier(Qnatnum);
1657 set_specifier_caching(Vtoolbar_border_width[RIGHT_TOOLBAR],
1658 offsetof(struct window,
1659 toolbar_border_width[RIGHT_TOOLBAR]),
1660 toolbar_geometry_changed_in_window,
1661 offsetof(struct frame,
1662 toolbar_border_width[RIGHT_TOOLBAR]),
1663 frame_size_slipped, 0);
1667 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
1669 #ifdef HAVE_X_WINDOWS
1670 fb = Fcons(Fcons(list1(Qx), make_int(DEFAULT_TOOLBAR_BORDER_WIDTH)),
1674 set_specifier_fallback(Vdefault_toolbar_border_width, fb);
1676 set_specifier_fallback(Vtoolbar_border_width[TOP_TOOLBAR],
1677 Vdefault_toolbar_border_width);
1678 fb = list1(Fcons(Qnil, Qzero));
1679 set_specifier_fallback(Vtoolbar_border_width[BOTTOM_TOOLBAR], fb);
1680 set_specifier_fallback(Vtoolbar_border_width[LEFT_TOOLBAR], fb);
1681 set_specifier_fallback(Vtoolbar_border_width[RIGHT_TOOLBAR], fb);
1683 DEFVAR_SPECIFIER("default-toolbar-visible-p", &Vdefault_toolbar_visible_p /*
1684 *Whether the default toolbar is visible.
1685 This is a specifier; use `set-specifier' to change it.
1687 The position of the default toolbar is specified by the function
1688 `set-default-toolbar-position'. If the corresponding position-specific
1689 toolbar visibility specifier (e.g. `top-toolbar-visible-p' if
1690 `default-toolbar-position' is 'top) does not specify a visible-p value
1691 in a particular domain (a window or a frame), then the value of
1692 `default-toolbar-visible-p' in that domain, if any, will be used
1695 Both window domains and frame domains are used internally, for
1696 different purposes. The distinction here is exactly the same as
1697 for thickness specifiers; see `default-toolbar-height' for more
1700 `default-toolbar-visible-p' and all of the position-specific toolbar
1701 visibility specifiers have a fallback value of true.
1703 Vdefault_toolbar_visible_p = Fmake_specifier(Qboolean);
1704 set_specifier_caching(Vdefault_toolbar_visible_p,
1705 offsetof(struct window,
1706 default_toolbar_visible_p),
1707 default_toolbar_visible_p_changed_in_window,
1708 offsetof(struct frame, default_toolbar_visible_p),
1709 default_toolbar_visible_p_changed_in_frame, 0);
1711 DEFVAR_SPECIFIER("top-toolbar-visible-p", &Vtoolbar_visible_p[TOP_TOOLBAR] /*
1712 *Whether the top toolbar is visible.
1713 This is a specifier; use `set-specifier' to change it.
1715 See `default-toolbar-visible-p' for more information.
1717 Vtoolbar_visible_p[TOP_TOOLBAR] = Fmake_specifier(Qboolean);
1718 set_specifier_caching(Vtoolbar_visible_p[TOP_TOOLBAR],
1719 offsetof(struct window,
1720 toolbar_visible_p[TOP_TOOLBAR]),
1721 toolbar_geometry_changed_in_window,
1722 offsetof(struct frame,
1723 toolbar_visible_p[TOP_TOOLBAR]),
1724 frame_size_slipped, 0);
1726 DEFVAR_SPECIFIER("bottom-toolbar-visible-p", &Vtoolbar_visible_p[BOTTOM_TOOLBAR] /*
1727 *Whether the bottom toolbar is visible.
1728 This is a specifier; use `set-specifier' to change it.
1730 See `default-toolbar-visible-p' for more information.
1732 Vtoolbar_visible_p[BOTTOM_TOOLBAR] = Fmake_specifier(Qboolean);
1733 set_specifier_caching(Vtoolbar_visible_p[BOTTOM_TOOLBAR],
1734 offsetof(struct window,
1735 toolbar_visible_p[BOTTOM_TOOLBAR]),
1736 toolbar_geometry_changed_in_window,
1737 offsetof(struct frame,
1738 toolbar_visible_p[BOTTOM_TOOLBAR]),
1739 frame_size_slipped, 0);
1741 DEFVAR_SPECIFIER("left-toolbar-visible-p", &Vtoolbar_visible_p[LEFT_TOOLBAR] /*
1742 *Whether the left toolbar is visible.
1743 This is a specifier; use `set-specifier' to change it.
1745 See `default-toolbar-visible-p' for more information.
1747 Vtoolbar_visible_p[LEFT_TOOLBAR] = Fmake_specifier(Qboolean);
1748 set_specifier_caching(Vtoolbar_visible_p[LEFT_TOOLBAR],
1749 offsetof(struct window,
1750 toolbar_visible_p[LEFT_TOOLBAR]),
1751 toolbar_geometry_changed_in_window,
1752 offsetof(struct frame,
1753 toolbar_visible_p[LEFT_TOOLBAR]),
1754 frame_size_slipped, 0);
1756 DEFVAR_SPECIFIER("right-toolbar-visible-p", &Vtoolbar_visible_p[RIGHT_TOOLBAR] /*
1757 *Whether the right toolbar is visible.
1758 This is a specifier; use `set-specifier' to change it.
1760 See `default-toolbar-visible-p' for more information.
1762 Vtoolbar_visible_p[RIGHT_TOOLBAR] = Fmake_specifier(Qboolean);
1763 set_specifier_caching(Vtoolbar_visible_p[RIGHT_TOOLBAR],
1764 offsetof(struct window,
1765 toolbar_visible_p[RIGHT_TOOLBAR]),
1766 toolbar_geometry_changed_in_window,
1767 offsetof(struct frame,
1768 toolbar_visible_p[RIGHT_TOOLBAR]),
1769 frame_size_slipped, 0);
1771 /* initially, top inherits from default; this can be
1772 changed with `set-default-toolbar-position'. */
1773 fb = list1(Fcons(Qnil, Qt));
1774 set_specifier_fallback(Vdefault_toolbar_visible_p, fb);
1775 set_specifier_fallback(Vtoolbar_visible_p[TOP_TOOLBAR],
1776 Vdefault_toolbar_visible_p);
1777 set_specifier_fallback(Vtoolbar_visible_p[BOTTOM_TOOLBAR], fb);
1778 set_specifier_fallback(Vtoolbar_visible_p[LEFT_TOOLBAR], fb);
1779 set_specifier_fallback(Vtoolbar_visible_p[RIGHT_TOOLBAR], fb);
1781 DEFVAR_SPECIFIER("toolbar-buttons-captioned-p", &Vtoolbar_buttons_captioned_p /*
1782 *Whether the toolbar buttons are captioned.
1783 This will only have a visible effect for those toolbar buttons which had
1784 captioned versions specified.
1785 This is a specifier; use `set-specifier' to change it.
1787 Vtoolbar_buttons_captioned_p = Fmake_specifier(Qboolean);
1788 set_specifier_caching(Vtoolbar_buttons_captioned_p,
1789 offsetof(struct window,
1790 toolbar_buttons_captioned_p),
1791 toolbar_buttons_captioned_p_changed, 0, 0, 0);
1792 set_specifier_fallback(Vtoolbar_buttons_captioned_p,
1793 list1(Fcons(Qnil, Qt)));