comparison src/glyphs-widget.c @ 863:42375619fa45

[xemacs-hg @ 2002-06-04 06:03:59 by andyp] merge 21.4 windows changes, minimally tested
author andyp
date Tue, 04 Jun 2002 06:05:53 +0000
parents 2b6fa2618f76
children 613552a02607
comparison
equal deleted inserted replaced
862:278c743f1578 863:42375619fa45
1 /* Widget-specific glyph objects. 1 /* Widget-specific glyph objects.
2 Copyright (C) 1998, 1999, 2000 Andy Piper. 2 Copyright (C) 1998, 1999, 2000, 2002 Andy Piper.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify it 6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the 7 under the terms of the GNU General Public License as published by the
59 DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout); 59 DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout);
60 Lisp_Object Qnative_layout; 60 Lisp_Object Qnative_layout;
61 61
62 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; 62 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
63 Lisp_Object Qmake_glyph; 63 Lisp_Object Qmake_glyph;
64 Lisp_Object Vwidget_border_width;
65
66 static int widget_border_width (Lisp_Object domain);
67 static int widget_spacing (Lisp_Object domain);
68 static void widget_query_string_geometry (Lisp_Object string, Lisp_Object face,
69 int *width, int *height, Lisp_Object domain);
64 70
65 #ifdef DEBUG_WIDGETS 71 #ifdef DEBUG_WIDGETS
66 int debug_widget_instances; 72 int debug_widget_instances;
67 #endif 73 #endif
68 74
117 } 123 }
118 124
119 static void 125 static void
120 check_valid_justification (Lisp_Object data) 126 check_valid_justification (Lisp_Object data)
121 { 127 {
122 if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter)) 128 if (!EQ (data, Qleft)
129 &&
130 !EQ (data, Qright)
131 &&
132 !EQ (data, Qtop)
133 &&
134 !EQ (data, Qbottom)
135 &&
136 !EQ (data, Qcenter))
123 invalid_constant ("unknown justification for layout", data); 137 invalid_constant ("unknown justification for layout", data);
124 } 138 }
125 139
126 static void 140 static void
127 check_valid_border (Lisp_Object data) 141 check_valid_border (Lisp_Object data)
235 { 249 {
236 XVECTOR_DATA (inst)[i+1] = val; 250 XVECTOR_DATA (inst)[i+1] = val;
237 break; 251 break;
238 } 252 }
239 } 253 }
254 }
255
256 /* Determine the border with of the widget. */
257 static int
258 widget_border_width (Lisp_Object domain)
259 {
260 /* #### FIXME -- need to use specifiers (Vwidget_border_width) for
261 some portion of this. */
262 if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain),
263 widget_border_width))
264 return DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ());
265 else
266 return DEFAULT_WIDGET_BORDER_WIDTH;
267 }
268
269 static int
270 widget_instance_border_width (Lisp_Image_Instance* ii)
271 {
272 return widget_border_width (IMAGE_INSTANCE_DOMAIN (ii));
273 }
274
275 /* #### Its not clear to me what the value of logical_unit_height should
276 be, or whether it should even depend on the current
277 image_instance. It really should probably only depend on the
278 default widget face and the domain, however you can envisage users
279 wanting different logical units for nested layouts - so using the
280 properties of the current lahyout is probably not so dumb. */
281 static int
282 logical_unit_height (Lisp_Object text, Lisp_Object face, Lisp_Object domain)
283 {
284 int charheight = 0;
285 widget_query_string_geometry (text, face,
286 0, &charheight, domain);
287 /* For the returned value to be useful it needs to be big enough to
288 accomodate the largest single-height widget. This is currently
289 the edit-field. */
290 return charheight + 2 * widget_spacing (domain)
291 + 4 * widget_border_width (domain);
292 }
293
294 static int
295 widget_logical_unit_height (Lisp_Image_Instance* ii)
296 {
297 return logical_unit_height (NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)) ?
298 IMAGE_INSTANCE_NAME (ii)
299 : IMAGE_INSTANCE_WIDGET_TEXT (ii),
300 IMAGE_INSTANCE_WIDGET_FACE (ii),
301 IMAGE_INSTANCE_DOMAIN (ii));
240 } 302 }
241 303
242 /* Wire widget property invocations to specific widgets. The problem 304 /* Wire widget property invocations to specific widgets. The problem
243 we are solving here is that when instantiators get converted to 305 we are solving here is that when instantiators get converted to
244 instances they lose some type information (they just become 306 instances they lose some type information (they just become
423 update the widget's size as it may have been changed by the the 485 update the widget's size as it may have been changed by the the
424 layout routines. We also do this here so that explicit resizing 486 layout routines. We also do this here so that explicit resizing
425 from lisp does not result in synchronous updates. Do this last so 487 from lisp does not result in synchronous updates. Do this last so
426 that format-specific methods have an opportunity to prevent 488 that format-specific methods have an opportunity to prevent
427 wholesale changes - e.g. rebuilding tabs. */ 489 wholesale changes - e.g. rebuilding tabs. */
428 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), redisplay_widget, (ii)); 490 MAYBE_DEVMETH (DOMAIN_XDEVICE (IMAGE_INSTANCE_DOMAIN (ii)),
491 redisplay_widget, (ii));
429 492
430 /* Pick up the items we recorded earlier. */ 493 /* Pick up the items we recorded earlier. */
431 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) 494 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
432 { 495 {
433 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 496 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
446 DEVMETH (d, widget_query_string_geometry, 509 DEVMETH (d, widget_query_string_geometry,
447 (string, face, width, height, domain)); 510 (string, face, width, height, domain));
448 else 511 else
449 query_string_geometry (string, face, width, height, 0, domain); 512 query_string_geometry (string, face, width, height, 0, domain);
450 513
514 }
515
516 /* Determine the spacing of the widget. */
517 static int
518 widget_spacing (Lisp_Object domain)
519 {
520 if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_spacing))
521 return DEVMETH (DOMAIN_XDEVICE (domain),
522 widget_spacing, (0));
523 else
524 return DEFAULT_WIDGET_SPACING;
451 } 525 }
452 526
453 /* Query for a widgets desired geometry. If no type specific method is 527 /* Query for a widgets desired geometry. If no type specific method is
454 provided then use the widget text to calculate sizes. */ 528 provided then use the widget text to calculate sizes. */
455 static void 529 static void
496 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), 570 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
497 IMAGE_INSTANCE_WIDGET_FACE (ii), 571 IMAGE_INSTANCE_WIDGET_FACE (ii),
498 &w, &h, domain); 572 &w, &h, domain);
499 /* Adjust the size for borders. */ 573 /* Adjust the size for borders. */
500 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) 574 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
501 *width = w + 2 * WIDGET_BORDER_WIDTH; 575 *width = w + 2 * widget_instance_border_width (ii);
502 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) 576 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
503 *height = h + 2 * WIDGET_BORDER_HEIGHT; 577 *height = h + 2 * widget_instance_border_width (ii);
504 } 578 }
505 } 579 }
506 /* Finish off with dynamic sizing. */ 580 /* Finish off with dynamic sizing. */
507 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii))) 581 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
508 { 582 {
612 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil; 686 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
613 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil; 687 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
614 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1; 688 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
615 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1; 689 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
616 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL; 690 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL;
617 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0; 691 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = 0;
692 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = 0;
618 } 693 }
619 694
620 /* Instantiate a button widget. Unfortunately instantiated widgets are 695 /* Instantiate a button widget. Unfortunately instantiated widgets are
621 particular to a frame since they need to have a parent. It's not 696 particular to a frame since they need to have a parent. It's not
622 like images where you just select the image into the context you 697 like images where you just select the image into the context you
730 805
731 /* Taking the default face information when the user has specified 806 /* Taking the default face information when the user has specified
732 size in characters is probably as good as any since the widget 807 size in characters is probably as good as any since the widget
733 face is more likely to be proportional and thus give inadequate 808 face is more likely to be proportional and thus give inadequate
734 results. Using character sizes can only ever be approximate 809 results. Using character sizes can only ever be approximate
735 anyway. */ 810 anyway. :height is measured in logical characters which take into
736 if (tw || th) 811 account the borders and spacing on widgets. */
737 { 812 if (tw)
738 int charwidth, charheight; 813 {
739 default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0); 814 int charwidth;
740 if (tw) 815 default_face_font_info (domain, 0, 0, 0, &charwidth, 0);
741 pw = charwidth * tw; 816 pw = ROUND_UP (charwidth * tw + 4 * widget_instance_border_width (ii), charwidth);
742 if (th) 817 }
743 ph = charheight * th; 818
819 /* For heights the widget face is more appropriate. */
820 if (th == 1)
821 {
822 int charheight;
823 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
824 {
825 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
826 IMAGE_INSTANCE_WIDGET_FACE (ii),
827 0, &charheight, domain);
828 }
829 else
830 {
831 default_face_font_info (domain, 0, 0, &charheight, 0, 0);
832 }
833 ph = (charheight + 2 * widget_instance_border_width (ii)) * th;
834 }
835 /* For heights > 1 use logical units. */
836 else if (th > 1)
837 {
838 ph = widget_logical_unit_height (ii) * th;
744 } 839 }
745 840
746 /* for a widget with an image pick up the dimensions from that */ 841 /* for a widget with an image pick up the dimensions from that */
747 if (!NILP (glyph)) 842 if (!NILP (glyph))
748 { 843 {
749 if (!pw) 844 if (!pw)
750 pw = glyph_width (glyph, image_instance) + 2 * WIDGET_BORDER_WIDTH; 845 pw = glyph_width (glyph, image_instance) + 2 * widget_instance_border_width (ii);
751 if (!ph) 846 if (!ph)
752 ph = glyph_height (glyph, image_instance) + 2 * WIDGET_BORDER_HEIGHT; 847 ph = glyph_height (glyph, image_instance) + 2 * widget_instance_border_width (ii);
753 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; 848 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
754 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; 849 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
755 } 850 }
756 851
757 /* Pick up the margin width. */ 852 /* Pick up the margin width. */
794 IMAGE_INSTANCE_WIDGET_FACE (ii), 889 IMAGE_INSTANCE_WIDGET_FACE (ii),
795 &w, &h, domain); 890 &w, &h, domain);
796 /* Adjust the size for borders. */ 891 /* Adjust the size for borders. */
797 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) 892 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
798 { 893 {
799 *width = w + 2 * WIDGET_BORDER_WIDTH; 894 *width = w + 3 * widget_instance_border_width (ii);
800 895
801 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio) 896 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio)
802 || 897 ||
803 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle)) 898 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle))
804 /* This is an approximation to the size of the actual button bit. */ 899 /* This is an approximation to the size of the actual button bit. */
805 *width += 12; 900 *width += 12;
806 } 901 }
807 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) 902 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
808 *height = h + 2 * WIDGET_BORDER_HEIGHT; 903 *height = h + 3 * widget_instance_border_width (ii);
904 }
905
906 /* Get the geometry of an edit field. */
907 static void
908 edit_field_query_geometry (Lisp_Object image_instance,
909 int* width, int* height,
910 enum image_instance_geometry disp, Lisp_Object domain)
911 {
912 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
913 int w, h;
914 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
915 IMAGE_INSTANCE_WIDGET_FACE (ii),
916 &w, &h, domain);
917 /* Adjust the size for borders. */
918 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
919 *width = w + 4 * widget_instance_border_width (ii);
920 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
921 *height = h + 4 * widget_instance_border_width (ii);
809 } 922 }
810 923
811 /* tree-view geometry - get the height right */ 924 /* tree-view geometry - get the height right */
812 static void 925 static void
813 tree_view_query_geometry (Lisp_Object image_instance, 926 tree_view_query_geometry (Lisp_Object image_instance,
826 width, 0, domain); 939 width, 0, domain);
827 } 940 }
828 if (*height) 941 if (*height)
829 { 942 {
830 int len, h; 943 int len, h;
944 /* #### widget face would be better here. */
831 default_face_font_info (domain, 0, 0, &h, 0, 0); 945 default_face_font_info (domain, 0, 0, &h, 0, 0);
832 GET_LIST_LENGTH (items, len); 946 GET_LIST_LENGTH (items, len);
833 *height = len * h; 947 *height = len * h;
834 } 948 }
835 } 949 }
849 LIST_LOOP (rest, items) 963 LIST_LOOP (rest, items)
850 { 964 {
851 int h, w; 965 int h, w;
852 966
853 widget_query_string_geometry (XGUI_ITEM (XCAR (rest))->name, 967 widget_query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
854 IMAGE_INSTANCE_WIDGET_FACE (ii), 968 IMAGE_INSTANCE_WIDGET_FACE (ii),
855 &w, &h, domain); 969 &w, &h, domain);
856 tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */ 970 tw += 5 * widget_instance_border_width (ii); /* some bias */
857 tw += w; 971 tw += w;
858 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT); 972 th = max (th, h + 2 * widget_instance_border_width (ii));
859 } 973 }
860 974
861 /* Fixup returned values depending on orientation. */ 975 /* Fixup returned values depending on orientation. */
862 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)) 976 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
863 { 977 {
963 layout_update (Lisp_Object image_instance, Lisp_Object instantiator) 1077 layout_update (Lisp_Object image_instance, Lisp_Object instantiator)
964 { 1078 {
965 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1079 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
966 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); 1080 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
967 Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border); 1081 Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border);
1082 Lisp_Object justify = find_keyword_in_vector (instantiator, Q_justify);
1083 Lisp_Object hjustify = find_keyword_in_vector (instantiator, Q_horizontally_justify);
1084 Lisp_Object vjustify = find_keyword_in_vector (instantiator, Q_vertically_justify);
968 Lisp_Object border = Qnil; 1085 Lisp_Object border = Qnil;
969 Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii); 1086 Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
970 int structure_changed = 0; 1087 int structure_changed = 0;
971 struct gcpro gcpro1; 1088 struct gcpro gcpro1;
972 1089
1090 /* Pick up horizontal justification, left is the default.*/
1091 if (!NILP (hjustify))
1092 {
1093 if (EQ (hjustify, Qright) || EQ (hjustify, Qbottom))
1094 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_RIGHT;
1095 else if (EQ (hjustify, Qcenter))
1096 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER;
1097 }
1098 /* If not set use general justification. */
1099 else if (!NILP (justify))
1100 {
1101 if (EQ (justify, Qright) || EQ (justify, Qbottom))
1102 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_RIGHT;
1103 else if (EQ (justify, Qcenter))
1104 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER;
1105 }
1106
1107 /* Pick up vertical justification, top is the default. */
1108 if (!NILP (vjustify))
1109 {
1110 if (EQ (vjustify, Qright) || EQ (vjustify, Qbottom))
1111 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_BOTTOM;
1112 else if (EQ (vjustify, Qcenter))
1113 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER;
1114 }
1115 /* If not set use general justification. */
1116 else if (!NILP (justify))
1117 {
1118 if (EQ (justify, Qright) || EQ (justify, Qbottom))
1119 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_BOTTOM;
1120 else if (EQ (justify, Qcenter))
1121 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER;
1122 }
1123
973 /* We want to avoid consing if we can. This is quite awkward because 1124 /* We want to avoid consing if we can. This is quite awkward because
974 we have to deal with the border as well as the items. */ 1125 we have to deal with the border as well as the items. */
975
976 GCPRO1 (border); 1126 GCPRO1 (border);
977 1127
978 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) 1128 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
979 { 1129 {
980 border = XCAR (children); 1130 border = XCAR (children);
1122 a glyph-face or image-instance face. All other glyphs are 1272 a glyph-face or image-instance face. All other glyphs are
1123 essentially fixed in appearance. Perhaps the problem is that text 1273 essentially fixed in appearance. Perhaps the problem is that text
1124 glyphs are cached on a device basis like most other glyphs. Instead 1274 glyphs are cached on a device basis like most other glyphs. Instead
1125 they should be cached per-window and then the instance would be 1275 they should be cached per-window and then the instance would be
1126 fixed and we wouldn't have to mess around with font metrics and the 1276 fixed and we wouldn't have to mess around with font metrics and the
1127 rest. */ 1277 rest.
1278
1279 Another sizing problem is alignment. We provide layout widgets that
1280 allow users to stack widgets vertically or horizontally. These
1281 layouts also allow the widgets to be centered (space evenly
1282 distributed), left or right justified (fixed spacing widgets
1283 stacked against the left, righ, top or bottom edge). Unfortunately
1284 this doesn't allow widgets in different layouts to be aligned. For
1285 instance how should the search dialog be organized for alignment?
1286 The obvious choice of two vertical columns does not work since the
1287 size of individual widgets will affect where they get placed. The
1288 same is true for several rows of widgets. To solve this problem we
1289 introduce the notion of `logical_unit_height'. This is a size
1290 quantity that is designed to be big enough to accomodate the
1291 largest `single height unit'. The function
1292 widget_logical_unit_height() determines the value of this in
1293 pixels. It is dependent on the widget face and some combination of
1294 spacing and border-width. Thus if users specify left or right
1295 justification in a vertical layout they get something in logical
1296 units. To simplify this the functions
1297 `widget-logical-to-character-height' and
1298 `widget-logical-to-character-width' allow conversion between
1299 characters and logical units so that frames can be sized
1300 appropriately. */
1128 1301
1129 /* Query the geometry of a layout widget. We assume that we can only 1302 /* Query the geometry of a layout widget. We assume that we can only
1130 get here if the size is not already fixed. */ 1303 get here if the size is not already fixed. */
1131 static void 1304 static void
1132 layout_query_geometry (Lisp_Object image_instance, int* width, 1305 layout_query_geometry (Lisp_Object image_instance, int* width,
1134 Lisp_Object domain) 1307 Lisp_Object domain)
1135 { 1308 {
1136 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1309 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1137 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest; 1310 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
1138 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0; 1311 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
1139 int gheight, gwidth; 1312 int gheight, gwidth, luh;
1140 1313
1141 /* If we are not initialized then we won't have any children. */ 1314 /* If we are not initialized then we won't have any children. */
1142 if (!IMAGE_INSTANCE_INITIALIZED (ii)) 1315 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1143 return; 1316 return;
1144 1317
1150 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) 1323 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
1151 && 1324 &&
1152 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) 1325 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
1153 return; 1326 return;
1154 1327
1328 luh = widget_logical_unit_height (ii);
1329
1155 /* Pick up the border text if we have one. */ 1330 /* Pick up the border text if we have one. */
1156 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) 1331 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1157 { 1332 {
1158 glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp, 1333 glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp,
1159 image_instance); 1334 image_instance);
1160 ph_adjust = gheight / 2; 1335 ph_adjust = gheight;
1161 items = XCDR (items); 1336 items = XCDR (items);
1162 } 1337 }
1163 1338
1164 /* Flip through the items to work out how much stuff we have to display */ 1339 /* Flip through the items to work out how much stuff we have to display */
1165 LIST_LOOP (rest, items) 1340 LIST_LOOP (rest, items)
1166 { 1341 {
1167 Lisp_Object glyph = XCAR (rest); 1342 Lisp_Object glyph = XCAR (rest);
1168 glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance); 1343 glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance);
1169 1344
1170 nitems ++; 1345 nitems ++;
1171 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1346 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL)
1172 == LAYOUT_HORIZONTAL)
1173 { 1347 {
1174 maxph = max (maxph, gheight); 1348 maxph = max (maxph, gheight);
1175 maxpw += gwidth; 1349 maxpw += gwidth;
1176 } 1350 }
1177 else 1351 else
1188 Lisp_Object dynamic_width = 1362 Lisp_Object dynamic_width =
1189 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)); 1363 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
1190 if (INTP (dynamic_width)) 1364 if (INTP (dynamic_width))
1191 *width = XINT (dynamic_width); 1365 *width = XINT (dynamic_width);
1192 } 1366 }
1193 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1367 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL)
1194 == LAYOUT_HORIZONTAL) 1368 {
1195 *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH + 1369 *width = maxpw + ((nitems + 1) * widget_instance_border_width (ii) +
1196 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2; 1370 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2;
1371 }
1197 else 1372 else
1198 *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 + 1373 {
1199 IMAGE_INSTANCE_MARGIN_WIDTH (ii)); 1374 *width = maxpw + 2 * (widget_instance_border_width (ii) * 2 +
1375 IMAGE_INSTANCE_MARGIN_WIDTH (ii));
1376 }
1200 1377
1201 /* Work out vertical spacings. */ 1378 /* Work out vertical spacings. */
1202 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii))) 1379 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
1203 { 1380 {
1204 Lisp_Object dynamic_height = 1381 Lisp_Object dynamic_height =
1205 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)); 1382 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
1206 if (INTP (dynamic_height)) 1383 if (INTP (dynamic_height))
1207 *height = XINT (dynamic_height); 1384 *height = XINT (dynamic_height);
1208 } 1385 }
1209 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1386 else if (IMAGE_INSTANCE_SUBWINDOW_LOGICAL_LAYOUT (ii))
1210 == LAYOUT_VERTICAL) 1387 {
1211 *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT + 1388 *height = nitems * luh + ph_adjust;
1212 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; 1389 }
1390 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_VERTICAL)
1391 {
1392 *height = maxph + ((nitems + 1) * widget_instance_border_width (ii) +
1393 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1394 }
1213 else 1395 else
1214 *height = maxph + (2 * WIDGET_BORDER_HEIGHT + 1396 {
1215 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; 1397 *height = maxph + (2 * widget_instance_border_width (ii) +
1398 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1399 }
1400 #ifdef DEBUG_WIDGET_OUTPUT
1401 stderr_out ("layout wants %dx%d\n", *width, *height);
1402 #endif
1216 } 1403 }
1217 1404
1218 int 1405 int
1219 layout_layout (Lisp_Object image_instance, 1406 layout_layout (Lisp_Object image_instance,
1220 int width, int height, int xoffset, int yoffset, 1407 int width, int height, int xoffset, int yoffset,
1224 Lisp_Object rest; 1411 Lisp_Object rest;
1225 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii); 1412 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
1226 int x, y, maxph = 0, maxpw = 0, nitems = 0, 1413 int x, y, maxph = 0, maxpw = 0, nitems = 0,
1227 horiz_spacing, vert_spacing, ph_adjust = 0; 1414 horiz_spacing, vert_spacing, ph_adjust = 0;
1228 int gheight, gwidth; 1415 int gheight, gwidth;
1416 /* See comments in widget_logical_unit_height(). */
1417 int luh = widget_logical_unit_height (ii);
1229 1418
1230 /* If we are not initialized then we won't have any children. */ 1419 /* If we are not initialized then we won't have any children. */
1231 if (!IMAGE_INSTANCE_INITIALIZED (ii)) 1420 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1232 return 0; 1421 return 0;
1233 1422
1234 /* Pick up the border text if we have one. */ 1423 #ifdef DEBUG_WIDGET_OUTPUT
1424 stderr_out ("layout output %dx%d\n", width, height);
1425 #endif
1426
1427 /* Pick up the border text if we have one. A border can have the
1428 values Qetched_in, Qetched_out, Qbevel_in, Qbevel_out or an
1429 integer. The first four just affect the display properties of the
1430 border that is drawn. The last is an offset and implies that the
1431 first item in the list of subcontrols is a text control that
1432 should be displayed on the border. */
1235 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) 1433 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1236 { 1434 {
1237 Lisp_Object border = XCAR (items); 1435 Lisp_Object border = XCAR (items);
1238 items = XCDR (items); 1436 items = XCDR (items);
1239 glyph_query_geometry (border, &gwidth, &gheight, 1437 glyph_query_geometry (border, &gwidth, &gheight,
1240 IMAGE_DESIRED_GEOMETRY, image_instance); 1438 IMAGE_DESIRED_GEOMETRY, image_instance);
1241 ph_adjust = gheight / 2; 1439 /* The vertical offset for subsequent items is the full height
1242 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); 1440 of the border glyph. */
1441 ph_adjust = gheight;
1442 /* The offset for the border is half the glyph height. */
1443 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (gheight / 2);
1243 1444
1244 /* #### Really, what should this be? */ 1445 /* #### Really, what should this be? */
1245 glyph_do_layout (border, gwidth, gheight, 10, 0, 1446 glyph_do_layout (border, gwidth, gheight, 10, 0,
1246 image_instance); 1447 image_instance);
1247 } 1448 }
1269 1470
1270 /* work out spacing between items and bounds of the layout */ 1471 /* work out spacing between items and bounds of the layout */
1271 if (width < maxpw) 1472 if (width < maxpw)
1272 /* The user wants a smaller space than the largest item, so we 1473 /* The user wants a smaller space than the largest item, so we
1273 just provide default spacing and will let the output routines 1474 just provide default spacing and will let the output routines
1274 clip.. */ 1475 clip. */
1275 horiz_spacing = WIDGET_BORDER_WIDTH * 2; 1476 horiz_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii));
1276 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1477 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1277 == LAYOUT_HORIZONTAL) 1478 == LAYOUT_HORIZONTAL)
1278 /* We have a larger area to display in so distribute the space 1479 /* We have a larger area to display in so distribute the space
1279 evenly. */ 1480 evenly. */
1280 horiz_spacing = (width - (maxpw + 1481 horiz_spacing = (width - (maxpw +
1281 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) 1482 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1282 / (nitems + 1); 1483 / (nitems + 1);
1283 else 1484 else
1284 horiz_spacing = (width - maxpw) / 2 1485 horiz_spacing = (width - maxpw) / 2
1285 - IMAGE_INSTANCE_MARGIN_WIDTH (ii); 1486 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1286 1487
1488 /* We are trying here to get widgets to line up when they are left
1489 or right justified vertically. This means that we must position
1490 widgets on logical unit boundaries, even though their height may
1491 be greater or less than a logical unit. In order to avoid
1492 clipping we need to determine how big the widget wants to be and
1493 then allocate as many logical units as necessary in order to
1494 accommodate it. */
1287 if (height < maxph) 1495 if (height < maxph)
1288 vert_spacing = WIDGET_BORDER_HEIGHT * 2; 1496 vert_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)) * 2;
1289 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1497 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1290 == LAYOUT_VERTICAL) 1498 == LAYOUT_VERTICAL)
1291 vert_spacing = (height - (maxph + ph_adjust + 1499 {
1292 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) 1500 if (!IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii))
1293 / (nitems + 1); 1501 vert_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)) * 2;
1502 else
1503 vert_spacing = (height - (maxph + ph_adjust +
1504 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1505 / (nitems + 1);
1506 }
1294 else 1507 else
1295 vert_spacing = (height - (maxph + ph_adjust)) / 2 1508 vert_spacing = (height - (maxph + ph_adjust)) / 2
1296 - IMAGE_INSTANCE_MARGIN_WIDTH (ii); 1509 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1297 1510
1298 y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii); 1511 y = yoffset = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1299 x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii); 1512 x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1300 1513
1301 /* Now flip through putting items where we want them, paying 1514 /* Now flip through putting items where we want them, paying
1302 attention to justification. Make sure we don't mess with the 1515 attention to justification. Make sure we don't mess with the
1303 border glyph. */ 1516 border glyph. */
1306 Lisp_Object glyph = XCAR (rest); 1519 Lisp_Object glyph = XCAR (rest);
1307 1520
1308 glyph_query_geometry (glyph, &gwidth, &gheight, 1521 glyph_query_geometry (glyph, &gwidth, &gheight,
1309 IMAGE_DESIRED_GEOMETRY, image_instance); 1522 IMAGE_DESIRED_GEOMETRY, image_instance);
1310 1523
1311 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1524 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL)
1312 == LAYOUT_HORIZONTAL) 1525 {
1313 { 1526 if (IMAGE_INSTANCE_SUBWINDOW_BOTTOM_JUSTIFIED (ii))
1314 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1315 == LAYOUT_JUSTIFY_RIGHT)
1316 y = height - (gheight + vert_spacing); 1527 y = height - (gheight + vert_spacing);
1317 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1528 else if (IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii))
1318 == LAYOUT_JUSTIFY_CENTER)
1319 y = (height - gheight) / 2; 1529 y = (height - gheight) / 2;
1320 } 1530 }
1321 else 1531 else
1322 { 1532 {
1323 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1533 if (IMAGE_INSTANCE_SUBWINDOW_RIGHT_JUSTIFIED (ii))
1324 == LAYOUT_JUSTIFY_RIGHT)
1325 x = width - (gwidth + horiz_spacing); 1534 x = width - (gwidth + horiz_spacing);
1326 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 1535 else if (IMAGE_INSTANCE_SUBWINDOW_H_CENTERED (ii))
1327 == LAYOUT_JUSTIFY_CENTER)
1328 x = (width - gwidth) / 2; 1536 x = (width - gwidth) / 2;
1329 } 1537 }
1330 1538
1331 /* Now layout subwidgets if they require it. */ 1539 /* Now layout subwidgets if they require it. */
1332 glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance); 1540 glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance);
1333 1541
1334 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 1542 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL)
1335 == LAYOUT_HORIZONTAL)
1336 { 1543 {
1337 x += (gwidth + horiz_spacing); 1544 x += (gwidth + horiz_spacing);
1338 } 1545 }
1339 else 1546 else
1340 { 1547 {
1341 y += (gheight + vert_spacing); 1548 y += (gheight + vert_spacing);
1549 if (!IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii))
1550 {
1551 /* justified, vertical layout, try and align on logical unit
1552 boundaries. */
1553 y = ROUND_UP (y - yoffset, luh) + yoffset;
1554 }
1342 } 1555 }
1343 1556
1344 } 1557 }
1345 return 1; 1558 return 1;
1346 } 1559 }
1401 IMAGE_INSTANCE_YOFFSET (ii), &dga); 1614 IMAGE_INSTANCE_YOFFSET (ii), &dga);
1402 } 1615 }
1403 return 1; 1616 return 1;
1404 } 1617 }
1405 1618
1619 DEFUN ("widget-logical-to-character-width", Fwidget_logical_to_character_width, 1, 3, 0, /*
1620 Convert the width in logical widget units to characters.
1621 Logical widget units do not take into account adjusments made for
1622 layout borders, so this adjusment is approximated.
1623 */
1624 (width, face, domain))
1625 {
1626 int w, neww, charwidth;
1627 int border_width = DEFAULT_WIDGET_BORDER_WIDTH;
1628
1629 if (NILP (domain))
1630 domain = Fselected_frame (Qnil);
1631
1632 CHECK_INT (width);
1633 w = XINT (width);
1634
1635 if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_border_width))
1636 border_width = DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ());
1637
1638 default_face_font_info (domain, 0, 0, 0, &charwidth, 0);
1639 neww = ROUND_UP (charwidth * w + 4 * border_width + 2 * widget_spacing (domain),
1640 charwidth) / charwidth;
1641
1642 return make_int (neww);
1643 }
1644
1645 DEFUN ("widget-logical-to-character-height", Fwidget_logical_to_character_height, 1, 3, 0, /*
1646 Convert the height in logical widget units to characters.
1647 Logical widget units do not take into account adjusments made for
1648 layout borders, so this adjustment is approximated.
1649
1650 If the components of a widget layout are justified to the top or the
1651 bottom then they are aligned in terms of `logical units'. This is a
1652 size quantity that is designed to be big enough to accomodate the
1653 largest `single height' widget. It is dependent on the widget face and
1654 some combination of spacing and border-width. Thus if you specify top
1655 or bottom justification in a vertical layout the subcontrols are laid
1656 out one per logical unit. This allows adjoining layouts to have
1657 identical alignment for their subcontrols.
1658
1659 Since frame sizes are measured in characters, this function allows you
1660 to do appropriate conversion between logical units and characters.
1661 */
1662 (height, face, domain))
1663 {
1664 int h, newh, charheight;
1665
1666 CHECK_INT (height);
1667 if (NILP (domain))
1668 domain = Fselected_frame (Qnil);
1669
1670 h = XINT (height);
1671
1672 default_face_font_info (domain, 0, 0, &charheight, 0, 0);
1673 newh = ROUND_UP (logical_unit_height (Fsymbol_name (Qwidget),
1674 Vwidget_face, domain) * h, charheight)
1675 / charheight;
1676
1677 return make_int (newh);
1678 }
1679
1406 1680
1407 /************************************************************************/ 1681 /************************************************************************/
1408 /* initialization */ 1682 /* initialization */
1409 /************************************************************************/ 1683 /************************************************************************/
1410 1684
1414 DEFSYMBOL (Qetched_in); 1688 DEFSYMBOL (Qetched_in);
1415 DEFSYMBOL (Qetched_out); 1689 DEFSYMBOL (Qetched_out);
1416 DEFSYMBOL (Qbevel_in); 1690 DEFSYMBOL (Qbevel_in);
1417 DEFSYMBOL (Qbevel_out); 1691 DEFSYMBOL (Qbevel_out);
1418 DEFSYMBOL (Qmake_glyph); 1692 DEFSYMBOL (Qmake_glyph);
1693
1694 DEFSUBR (Fwidget_logical_to_character_height);
1695 DEFSUBR (Fwidget_logical_to_character_width);
1419 } 1696 }
1420 1697
1421 #define VALID_GUI_KEYWORDS(type) do { \ 1698 #define VALID_GUI_KEYWORDS(type) do { \
1422 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \ 1699 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \
1423 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \ 1700 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
1477 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget); 1754 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1478 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget); 1755 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1479 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget); 1756 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1480 IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget); 1757 IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget);
1481 IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow); 1758 IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow);
1759 IIFORMAT_HAS_METHOD (edit_field, query_geometry);
1482 VALID_WIDGET_KEYWORDS (edit_field); 1760 VALID_WIDGET_KEYWORDS (edit_field);
1483 VALID_GUI_KEYWORDS (edit_field); 1761 VALID_GUI_KEYWORDS (edit_field);
1484 } 1762 }
1485 1763
1486 static void image_instantiator_combo_box (void) 1764 static void image_instantiator_combo_box (void)
1574 1852
1575 #define VALID_LAYOUT_KEYWORDS(layout) \ 1853 #define VALID_LAYOUT_KEYWORDS(layout) \
1576 VALID_WIDGET_KEYWORDS (layout); \ 1854 VALID_WIDGET_KEYWORDS (layout); \
1577 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \ 1855 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \
1578 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \ 1856 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \
1857 IIFORMAT_VALID_KEYWORD (layout, Q_vertically_justify, check_valid_justification); \
1858 IIFORMAT_VALID_KEYWORD (layout, Q_horizontally_justify, check_valid_justification); \
1579 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \ 1859 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \
1580 IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \ 1860 IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \
1581 IIFORMAT_VALID_KEYWORD (layout, Q_items, \ 1861 IIFORMAT_VALID_KEYWORD (layout, Q_items, \
1582 check_valid_instantiator_list) 1862 check_valid_instantiator_list)
1583 1863
1642 void 1922 void
1643 vars_of_glyphs_widget (void) 1923 vars_of_glyphs_widget (void)
1644 { 1924 {
1645 reinit_vars_of_glyphs_widget (); 1925 reinit_vars_of_glyphs_widget ();
1646 } 1926 }
1927
1928
1929 void
1930 specifier_vars_of_glyphs_widget (void)
1931 {
1932 DEFVAR_SPECIFIER ("widget-border-width",
1933 &Vwidget_border_width /*
1934 *Border width of widgets.
1935 This is a specifier; use `set-specifier' to change it.
1936 */ );
1937 Vwidget_border_width = Fmake_specifier (Qnatnum);
1938 }