Mercurial > hg > xemacs-beta
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 } |