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