Index: lisp/gutter-items.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/Attic/gutter-items.el,v retrieving revision 1.1.2.20 diff -u -r1.1.2.20 gutter-items.el --- lisp/gutter-items.el 1999/12/04 19:21:32 1.1.2.20 +++ lisp/gutter-items.el 2000/01/08 20:11:55 @@ -254,9 +254,7 @@ (last-nonminibuf-window frame-or-buffer))))) (set-image-instance-property inst :items (buffers-tab-items - nil locale)) - (resize-subwindow inst (gutter-pixel-width) nil)) - )))) + nil locale))))))) (defun remove-buffer-from-gutter-tab () "Remove the current buffer from the tab control in the gutter area." @@ -268,9 +266,7 @@ (setq buffers (build-buffers-tab-internal (list (get-buffer-create "*scratch*"))))) - (set-image-instance-property inst :items buffers) - (resize-subwindow inst (gutter-pixel-width) nil) - ))) + (set-image-instance-property inst :items buffers)))) (add-hook 'kill-buffer-hook 'remove-buffer-from-gutter-tab) (add-hook 'create-frame-hook 'update-tab-in-gutter) Index: src/event-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/event-msw.c,v retrieving revision 1.38.2.24 diff -u -r1.38.2.24 event-msw.c --- src/event-msw.c 1999/12/21 17:37:44 1.38.2.24 +++ src/event-msw.c 2000/01/08 20:12:10 @@ -2264,9 +2264,7 @@ VOID_TO_LISP (image_instance, ii); if (IMAGE_INSTANCEP (image_instance) && - IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET) - && - !NILP (XIMAGE_INSTANCE_WIDGET_FACE (image_instance))) + IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)) { /* set colors for the buttons */ HDC hdc = (HDC)wParam; Index: src/frame.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/frame.c,v retrieving revision 1.37.2.13 diff -u -r1.37.2.13 frame.c --- src/frame.c 2000/01/04 08:50:25 1.37.2.13 +++ src/frame.c 2000/01/08 20:12:22 @@ -2678,8 +2678,8 @@ window = FRAME_SELECTED_WINDOW (f); - egw = max (glyph_width (Vcontinuation_glyph, Vdefault_face, 0, window), - glyph_width (Vtruncation_glyph, Vdefault_face, 0, window)); + egw = max (glyph_width (Vcontinuation_glyph, window), + glyph_width (Vtruncation_glyph, window)); egw = max (egw, cpw); bdr = 2 * f->internal_border_width; obw = FRAME_SCROLLBAR_WIDTH (f) + FRAME_THEORETICAL_LEFT_TOOLBAR_WIDTH (f) + @@ -2854,9 +2854,9 @@ { int adjustment, trunc_width, cont_width; - trunc_width = glyph_width (Vtruncation_glyph, Vdefault_face, 0, + trunc_width = glyph_width (Vtruncation_glyph, FRAME_SELECTED_WINDOW (f)); - cont_width = glyph_width (Vcontinuation_glyph, Vdefault_face, 0, + cont_width = glyph_width (Vcontinuation_glyph, FRAME_SELECTED_WINDOW (f)); adjustment = max (trunc_width, cont_width); adjustment = max (adjustment, font_width); Index: src/glyphs-msw.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.c,v retrieving revision 1.21.2.32 diff -u -r1.21.2.32 glyphs-msw.c --- src/glyphs-msw.c 1999/12/23 02:50:44 1.21.2.32 +++ src/glyphs-msw.c 2000/01/08 20:12:30 @@ -1,5 +1,5 @@ /* mswindows-specific glyph objects. - Copyright (C) 1998, 1999 Andy Piper. + Copyright (C) 1998, 1999, 2000 Andy Piper. This file is part of XEmacs. @@ -2144,6 +2144,7 @@ static void mswindows_update_subwindow (struct Lisp_Image_Instance *p) { + /* Now do widget specific updates. */ if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) { /* buttons checked or otherwise */ @@ -2161,10 +2162,10 @@ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), WM_SETFONT, (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT - (XFONT_INSTANCE (widget_face_font_info - (IMAGE_INSTANCE_SUBWINDOW_FRAME (p), + (XFONT_INSTANCE (query_string_font + (IMAGE_INSTANCE_WIDGET_TEXT (p), IMAGE_INSTANCE_WIDGET_FACE (p), - 0, 0))), + IMAGE_INSTANCE_SUBWINDOW_FRAME (p)))), MAKELPARAM (TRUE, 0)); } } @@ -2344,9 +2345,7 @@ { id = mswindows_register_widget_instance (image_instance, domain); } - /* have to set the type this late in case there is no device - instantiation for a widget */ - IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; + if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm); @@ -2396,17 +2395,17 @@ /* set the widget font from the widget face */ SendMessage (wnd, WM_SETFONT, (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT - (XFONT_INSTANCE (widget_face_font_info - (domain, + (XFONT_INSTANCE (query_string_font + (IMAGE_INSTANCE_WIDGET_TEXT (ii), IMAGE_INSTANCE_WIDGET_FACE (ii), - 0, 0))), + domain))), MAKELPARAM (TRUE, 0)); } /* Instantiate a button widget. Unfortunately instantiated widgets are particular to a frame since they need to have a parent. It's not like images where you just select the image into the context you - want to display it in and BitBlt it. So images instances can have a + want to display it in and BitBlt it. So image instances can have a many-to-one relationship with things you see, whereas widgets can only be one-to-one (i.e. per frame) */ static void @@ -2438,6 +2437,8 @@ style = pgui->style; + /* #### consider using the default face for radio and toggle + buttons. */ if (EQ (style, Qradio)) { flags |= BS_RADIOBUTTON; @@ -2722,8 +2723,7 @@ Lisp_Object rest; Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), Q_items, Qnil); - int len; - GET_LIST_LENGTH (data, len); + int len, height; /* Maybe ought to generalise this more but it may be very windows specific. In windows the window height of a combo box is the @@ -2731,19 +2731,29 @@ before creating the window and then reset it to a single line after the window is created so that redisplay does the right thing. */ - widget_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, len + 1, 0, 0); + widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain); + /* We now have everything right apart from the height. */ + default_face_font_info (domain, 0, 0, &height, 0, 0); + GET_LIST_LENGTH (data, len); + + height = (height + WIDGET_BORDER_HEIGHT * 2 ) * len; + IMAGE_INSTANCE_HEIGHT (ii) = height; + + /* Now create the widget. */ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, dest_mask, domain, "COMBOBOX", WS_BORDER | WS_TABSTOP | CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_HASSTRINGS | WS_VSCROLL, WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT); - /* reset the height */ - widget_text_to_pixel_conversion (domain, - IMAGE_INSTANCE_WIDGET_FACE (ii), 1, 0, - &IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii), 0); + /* Reset the height. layout will probably do this safely, but better make sure. */ + image_instance_layout (image_instance, + IMAGE_UNSPECIFIED_GEOMETRY, + IMAGE_UNSPECIFIED_GEOMETRY, + domain); + wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); /* add items to the combo box */ SendMessage (wnd, CB_RESETCONTENT, 0, 0); @@ -2823,7 +2833,8 @@ GET_C_STRING_OS_DATA_ALLOCA (val, lparam); SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), WM_SETTEXT, 0, (LPARAM)lparam); - return Qt; + /* We don't return Qt here so that other widget methods can be + called afterwards. */ } return Qunbound; } Index: src/glyphs-widget.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/glyphs-widget.c,v retrieving revision 1.1.2.17 diff -u -r1.1.2.17 glyphs-widget.c --- src/glyphs-widget.c 1999/12/21 17:37:44 1.1.2.17 +++ src/glyphs-widget.c 2000/01/08 20:12:34 @@ -1,5 +1,5 @@ /* Widget-specific glyph objects. - Copyright (C) 1998, 1999 Andy Piper. + Copyright (C) 1998, 1999, 2000 Andy Piper. This file is part of XEmacs. @@ -60,50 +60,20 @@ Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border; Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; -#define WIDGET_BORDER_HEIGHT 4 -#define WIDGET_BORDER_WIDTH 4 - #ifdef DEBUG_WIDGETS int debug_widget_instances; #endif /* TODO: - more complex controls. - - tooltips for controls. + - tooltips for controls, especially buttons. */ -/* In windows normal windows work in pixels, dialog boxes work in +/* In MS-Windows normal windows work in pixels, dialog boxes work in dialog box units. Why? sigh. We could reuse the metrics for dialogs if this were not the case. As it is we have to position things pixel wise. I'm not even sure that X has this problem at least for buttons in groups. */ -Lisp_Object -widget_face_font_info (Lisp_Object domain, Lisp_Object face, - int *height, int *width) -{ - Lisp_Object font_instance = FACE_FONT (face, domain, Vcharset_ascii); - - if (height) - *height = XFONT_INSTANCE (font_instance)->height; - if (width) - *width = XFONT_INSTANCE (font_instance)->width; - - return font_instance; -} - -void -widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face, - int th, int tw, - int* height, int* width) -{ - int ch=0, cw=0; - widget_face_font_info (domain, face, &ch, &cw); - if (height) - *height = th * ch + 2 * WIDGET_BORDER_HEIGHT; - if (width) - *width = tw * cw + 2 * WIDGET_BORDER_WIDTH; -} - static int widget_possible_dest_types (void) { @@ -259,17 +229,17 @@ } } -/* wire widget property invocations to specific widgets ... The - problem we are solving here is that when instantiators get converted - to instances they lose some type information (they just become - subwindows or widgets for example). For widgets we need to preserve - this type information so that we can do widget specific operations on - the instances. This is encoded in the widget type - field. widget_property gets invoked by decoding the primary type - (Qwidget), widget property then invokes based on the secondary type - (Qedit_field for example). It is debatable that we should wire things in this - generalised way rather than treating widgets specially in - image_instance_property. */ +/* Wire widget property invocations to specific widgets. The problem + we are solving here is that when instantiators get converted to + instances they lose some type information (they just become + subwindows or widgets for example). For widgets we need to preserve + this type information so that we can do widget specific operations + on the instances. This is encoded in the widget type + field. widget_property gets invoked by decoding the primary type + (Qwidget), _property then invokes based on the secondary + type (Qedit_field for example). It is debatable whether we should + wire things in this generalised way rather than treating widgets + specially in image_instance_property. */ static Lisp_Object widget_property (Lisp_Object image_instance, Lisp_Object prop) { @@ -302,7 +272,14 @@ struct image_instantiator_methods* meths; Lisp_Object ret; - /* try device specific methods first ... */ + /* PIck up any generic properties that we might need to keep hold + of. */ + if (EQ (prop, Q_text)) + { + IMAGE_INSTANCE_WIDGET_TEXT (ii) = val; + } + + /* Now try device specific methods first ... */ meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), IMAGE_INSTANCE_WIDGET_TYPE (ii), ERROR_ME_NOT); @@ -329,6 +306,87 @@ return val; } +/* Query for a widgets desired geometry. If no type specific method is + provided then use the widget text to calculate sizes. */ +static void +widget_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, Lisp_Object domain) +{ + struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + struct image_instantiator_methods* meths; + + /* First just set up what we already have. */ + if (width) *width = IMAGE_INSTANCE_WIDTH (ii); + if (height) *height = IMAGE_INSTANCE_HEIGHT (ii); + + if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) + || + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) + { + /* .. then try device specific methods ... */ + meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + IMAGE_INSTANCE_WIDGET_TYPE (ii), + ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) + IIFORMAT_METH (meths, query_geometry, (image_instance, + width, height, disp, + domain)); + else + { + /* ... then format specific methods ... */ + meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), + ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) + IIFORMAT_METH (meths, query_geometry, (image_instance, + width, height, disp, + domain)); + else + { + + /* Then if we are allowed to resize the widget, make the + size the same as the text dimensions. */ + query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), + IMAGE_INSTANCE_WIDGET_FACE (ii), + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) ? + width : 0, + IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) ? + height : 0, 0, domain); + /* Adjust the size for borders. */ + if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) + *width += 2 * WIDGET_BORDER_WIDTH; + if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) + *height += 2 * WIDGET_BORDER_HEIGHT; + } + } + } +} + +static void +widget_layout (Lisp_Object image_instance, + unsigned int width, unsigned int height, Lisp_Object domain) +{ + struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + struct image_instantiator_methods* meths; + + /* .. then try device specific methods ... */ + meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + IMAGE_INSTANCE_WIDGET_TYPE (ii), + ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, layout)) + IIFORMAT_METH (meths, layout, (image_instance, + width, height, domain)); + else + { + /* ... then format specific methods ... */ + meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), + ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, layout)) + IIFORMAT_METH (meths, layout, (image_instance, + width, height, domain)); + } +} + static void widget_validate (Lisp_Object instantiator) { @@ -381,8 +439,10 @@ /* initialize_subwindow_image_instance (ii);*/ IMAGE_INSTANCE_WIDGET_TYPE (ii) = type; IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil; - IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face; + SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil); IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item (); + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1; + IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1; } /* Instantiate a button widget. Unfortunately instantiated widgets are @@ -392,10 +452,9 @@ many-to-one relationship with things you see, whereas widgets can only be one-to-one (i.e. per frame) */ void -widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain, int default_textheight, - int default_pixheight, int default_textwidth) +widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) { struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); Lisp_Object face = find_keyword_in_vector (instantiator, Q_face); @@ -419,7 +478,7 @@ /* retrieve the fg and bg colors */ if (!NILP (face)) - IMAGE_INSTANCE_WIDGET_FACE (ii) = Fget_face (face); + SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face)); /* data items for some widgets */ IMAGE_INSTANCE_WIDGET_PROPS (ii) = props; @@ -448,53 +507,73 @@ parse_gui_item_tree_children (items)); } - /* normalize size information */ - if (!NILP (width)) - tw = XINT (width); - if (!NILP (height)) - th = XINT (height); - if (!NILP (pixwidth)) - pw = XINT (pixwidth); - if (!NILP (pixheight)) - ph = XINT (pixheight); - - /* for a widget with an image pick up the dimensions from that */ - if (!NILP (glyph)) + /* Normalize size information. We now only assign sizes if the user + gives us some explicitly, or there are some constraints that we + can't change later on. Otherwise we postpone sizing until query + geometry gets called. */ + if (!NILP (pixwidth)) /* pixwidth takes precendent */ { - if (!pw && !tw) - pw = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain) - + 2 * WIDGET_BORDER_WIDTH; - if (!ph && !th) - ph = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain) - + 2 * WIDGET_BORDER_HEIGHT; + pw = XINT (pixwidth); + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; } - - /* if we still don' t have sizes, guess from text size */ - if (!tw && !pw) + else if (!NILP (width)) { - if (default_textwidth) - tw = default_textwidth; - else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) - tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii)); + tw = XINT (width); + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; } - if (!th && !ph) + if (!NILP (pixheight)) { - if (default_textheight) - th = default_textheight; - else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) - th = 1; - else - ph = default_pixheight; + ph = XINT (pixheight); + IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; } - - if (tw !=0 || th !=0) - widget_text_to_pixel_conversion (domain, - IMAGE_INSTANCE_WIDGET_FACE (ii), - th, tw, th ? &ph : 0, tw ? &pw : 0); + else if (!NILP (height) && XINT (height) > 1) + { + th = XINT (height); + IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; + } - IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw; - IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph; + /* Taking the default face information when the user has specified + size in characters is probably as good as any since the widget + face is more likely to be proportional and thus give inadequate + results. Using character sizes can only ever be approximate + anyway. */ + if (tw || th) + { + int charwidth, charheight; + default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0); + if (tw) + pw = charwidth * tw; + if (th) + ph = charheight * th; + } + + /* for a widget with an image pick up the dimensions from that */ + if (!NILP (glyph)) + { + if (!pw) + pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH; + if (!ph) + ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT; + IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; + } + + /* have to set the type this late in case there is no device + instantiation for a widget */ + IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; + + /* When we create the widgets the window system expects a valid + size, so If we still don' t have sizes, call layout to pick them + up. If query_geometry or layout relies on the widget being in + existence then we are in catch 22. */ + image_instance_layout (image_instance, + pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY, + ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY, + domain); + /* Layout has already been done so we don't need to re-layout. */ + IMAGE_INSTANCE_DIRTYP (ii) = 0; + #ifdef DEBUG_WIDGETS debug_widget_instances++; stderr_out ("instantiated "); @@ -503,65 +582,60 @@ #endif } +/* tree-view geometry - get the height right */ static void -widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) +tree_view_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, Lisp_Object domain) { - widget_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, 1, 0, 0); -} + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii); -/* tree-view generic instantiation - get the height right */ -static void -tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) -{ - Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), - Q_items, Qnil); - int len; - GET_LIST_LENGTH (data, len); - widget_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, len + 1, 0, 0); + + if (*width) + { + /* #### what should this be. reconsider when X has tree views. */ + query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), + IMAGE_INSTANCE_WIDGET_FACE (ii), + width, 0, 0, domain); + } + if (*height) + { + int len, h; + default_face_font_info (domain, 0, 0, &h, 0, 0); + GET_LIST_LENGTH (items, len); + *height = len * h; + } } +/* Get the geometry of a tab control. This is based on the number of + items and text therin in the tab control. */ static void -tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) +tab_control_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, Lisp_Object domain) { - Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), - Q_items, Qnil); + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii); Lisp_Object rest; - int len = 0; - LIST_LOOP (rest, data) + LIST_LOOP (rest, items) { - len += 3; /* some bias */ - if (STRINGP (XCAR (rest))) - len += XSTRING_LENGTH (XCAR (rest)); - else if (VECTORP (XCAR (rest))) + unsigned int h, w; + + query_string_geometry (XGUI_ITEM (XCAR (rest))->name, + IMAGE_INSTANCE_WIDGET_FACE (ii), + &w, &h, 0, domain); + if (width) { - Lisp_Object gui = gui_parse_item_keywords (XCAR (rest)); - len += XSTRING_LENGTH (XGUI_ITEM (gui)->name); + *width += 2 * WIDGET_BORDER_WIDTH; /* some bias */ + *width += w; } + if (height) + *height = max (*height, h); } - - widget_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, 0, 0, len); } -/* Instantiate a static control */ -static void -static_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) -{ - widget_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, 0, 4, 0); -} - /***************************************************************************** * widget layout * @@ -689,8 +763,8 @@ LIST_LOOP (rest, items) { Lisp_Object glyph = XCAR (rest); - int gheight = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain); - int gwidth = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain); + int gheight = glyph_height (glyph, domain); + int gwidth = glyph_width (glyph, domain); nitems ++; if (EQ (orient, Qhorizontal)) { @@ -738,7 +812,7 @@ XIMAGE_INSTANCE_XOFFSET (bglyph) = 10; /* Really, what should this be? */ XIMAGE_INSTANCE_YOFFSET (bglyph) = 0; - ph_adjust = (glyph_height (border, Qnil, DEFAULT_INDEX, domain) / 2); + ph_adjust = (glyph_height (border, domain) / 2); IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); } @@ -768,8 +842,8 @@ /* make sure the image is instantiated */ Lisp_Object glyph = XCAR (rest); Lisp_Object gii = glyph_image_instance (glyph, domain, ERROR_ME, 1); - int gwidth = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain); - int gheight = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain); + int gwidth = glyph_width (glyph, domain); + int gheight = glyph_height (glyph, domain); children = Fcons (gii, children); @@ -862,6 +1068,8 @@ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget"); IIFORMAT_HAS_METHOD (widget, property); IIFORMAT_HAS_METHOD (widget, set_property); + IIFORMAT_HAS_METHOD (widget, query_geometry); + IIFORMAT_HAS_METHOD (widget, layout); /* widget image-instantiator types - buttons */ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button"); @@ -917,7 +1125,8 @@ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view"); IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box); IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget); - IIFORMAT_HAS_METHOD (tree_view, instantiate); + IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget); + IIFORMAT_HAS_METHOD (tree_view, query_geometry); VALID_WIDGET_KEYWORDS (tree_view); VALID_GUI_KEYWORDS (tree_view); IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list); @@ -926,7 +1135,8 @@ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control"); IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box); IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget); - IIFORMAT_HAS_METHOD (tab_control, instantiate); + IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget); + IIFORMAT_HAS_METHOD (tab_control, query_geometry); VALID_WIDGET_KEYWORDS (tab_control); VALID_GUI_KEYWORDS (tab_control); IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list); @@ -934,7 +1144,7 @@ /* labels */ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label"); IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget); - IIFORMAT_HAS_SHARED_METHOD (label, instantiate, static); + IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget); VALID_WIDGET_KEYWORDS (label); IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string); Index: src/glyphs-x.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.c,v retrieving revision 1.49.2.41 diff -u -r1.49.2.41 glyphs-x.c --- src/glyphs-x.c 2000/01/01 05:05:29 1.49.2.41 +++ src/glyphs-x.c 2000/01/08 20:12:42 @@ -4,7 +4,7 @@ Copyright (C) 1995 Tinker Systems Copyright (C) 1995, 1996 Ben Wing Copyright (C) 1995 Sun Microsystems - Copyright (C) 1999 Andy Piper + Copyright (C) 1999, 2000 Andy Piper This file is part of XEmacs. @@ -2177,11 +2177,7 @@ lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), wv, True); free_widget_value_tree (wv); - /* We have to do this otherwise Motif will unceremoniously - resize us when the label gets set. */ - XtSetArg (al [0], XtNwidth, IMAGE_INSTANCE_WIDGET_WIDTH (p)); - XtSetArg (al [1], XtNheight, IMAGE_INSTANCE_WIDGET_HEIGHT (p)); - XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (p), al, 2); + /* subwindow resizing now gets done by the parent function. */ } #endif } @@ -2320,18 +2316,18 @@ #ifdef LWLIB_WIDGETS_MOTIF fontList = XmFontListCreate (FONT_INSTANCE_X_FONT - (XFONT_INSTANCE (widget_face_font_info - (domain, + (XFONT_INSTANCE (query_string_font + (IMAGE_INSTANCE_WIDGET_TEXT (ii), IMAGE_INSTANCE_WIDGET_FACE (ii), - 0, 0))), XmSTRING_DEFAULT_CHARSET); + domain))), XmSTRING_DEFAULT_CHARSET); lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList); #endif lw_add_widget_value_arg (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT - (XFONT_INSTANCE (widget_face_font_info - (domain, + (XFONT_INSTANCE (query_string_font + (IMAGE_INSTANCE_WIDGET_TEXT (ii), IMAGE_INSTANCE_WIDGET_FACE (ii), - 0, 0)))); + domain)))); } static void @@ -2485,7 +2481,6 @@ GET_C_STRING_OS_DATA_ALLOCA (val, str); wv->value = str; lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False); - return Qt; } /* Modify the text properties of the widget */ @@ -2494,7 +2489,6 @@ widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); update_widget_face (wv, ii, IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False); - return Qt; } return Qunbound; } @@ -2634,8 +2628,8 @@ widget_value * wv = 0; /* This is not done generically because of sizing problems under mswindows. */ - widget_instantiate_1 (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, 1, 0, 0); + widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain); wv = gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); Index: src/glyphs.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v retrieving revision 1.23.2.37 diff -u -r1.23.2.37 glyphs.c --- src/glyphs.c 1999/12/21 17:37:46 1.23.2.37 +++ src/glyphs.c 2000/01/08 20:12:56 @@ -3,7 +3,7 @@ Copyright (C) 1995 Tinker Systems Copyright (C) 1995, 1996 Ben Wing Copyright (C) 1995 Sun Microsystems - Copyright (C) 1998, 1999 Andy Piper + Copyright (C) 1998, 1999, 2000 Andy Piper This file is part of XEmacs. @@ -24,7 +24,8 @@ /* Synched up with: Not in FSF. */ -/* Written by Ben Wing and Chuck Thompson. */ +/* Written by Ben Wing and Chuck Thompson. Heavily modified / + rewritten by Andy Piper. */ #include #include "lisp.h" @@ -122,7 +123,7 @@ image_instantiator_format_entry_dynarr * the_image_instantiator_format_entry_dynarr; -static Lisp_Object allocate_image_instance (Lisp_Object device); +static Lisp_Object allocate_image_instance (Lisp_Object device, Lisp_Object glyph); static void image_validate (Lisp_Object instantiator); static void glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property, @@ -575,9 +576,9 @@ instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask) + int dest_mask, Lisp_Object glyph) { - Lisp_Object ii = allocate_image_instance (device); + Lisp_Object ii = allocate_image_instance (device, glyph); struct image_instantiator_methods *meths; struct gcpro gcpro1; int methp = 0; @@ -622,6 +623,8 @@ struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); mark_object (i->name); + /* We don't mark the glyph reference since that would create a + circularity preventing GC. */ switch (IMAGE_INSTANCE_TYPE (i)) { case IMAGE_TEXT: @@ -754,13 +757,6 @@ break; case IMAGE_WIDGET: - /* - if (!NILP (IMAGE_INSTANCE_WIDGET_CALLBACK (ii))) - { - print_internal (IMAGE_INSTANCE_WIDGET_CALLBACK (ii), printcharfun, 0); - write_c_string (", ", printcharfun); - } - */ if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii))) { write_c_string (" (", printcharfun); @@ -842,7 +838,11 @@ if (d1 != d2) return 0; - if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)) + if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2) + || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2) + || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2) + || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2) + || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2)) return 0; if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2), depth + 1)) @@ -863,11 +863,7 @@ case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: case IMAGE_POINTER: - if (!(IMAGE_INSTANCE_PIXMAP_WIDTH (i1) == - IMAGE_INSTANCE_PIXMAP_WIDTH (i2) && - IMAGE_INSTANCE_PIXMAP_HEIGHT (i1) == - IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) && - IMAGE_INSTANCE_PIXMAP_DEPTH (i1) == + if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) == IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && IMAGE_INSTANCE_PIXMAP_SLICE (i1) == IMAGE_INSTANCE_PIXMAP_SLICE (i2) && @@ -887,6 +883,8 @@ case IMAGE_WIDGET: if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), IMAGE_INSTANCE_WIDGET_TYPE (i2)) + && IMAGE_INSTANCE_SUBWINDOW_ID (i1) == + IMAGE_INSTANCE_SUBWINDOW_ID (i2) && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1), IMAGE_INSTANCE_WIDGET_ITEMS (i2), depth + 1) @@ -895,6 +893,8 @@ depth + 1) )) return 0; + break; + case IMAGE_LAYOUT: if (IMAGE_INSTANCE_TYPE (i1) == IMAGE_LAYOUT && @@ -905,12 +905,10 @@ IMAGE_INSTANCE_LAYOUT_CHILDREN (i2), depth + 1))) return 0; + break; + case IMAGE_SUBWINDOW: - if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) == - IMAGE_INSTANCE_SUBWINDOW_WIDTH (i2) && - IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i1) == - IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i2) && - IMAGE_INSTANCE_SUBWINDOW_ID (i1) == + if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) == IMAGE_INSTANCE_SUBWINDOW_ID (i2))) return 0; break; @@ -927,7 +925,9 @@ { struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); struct device *d = XDEVICE (i->device); - unsigned long hash = (unsigned long) d; + unsigned long hash = HASH3 ((unsigned long) d, + IMAGE_INSTANCE_WIDTH (i), + IMAGE_INSTANCE_HEIGHT (i)); switch (IMAGE_INSTANCE_TYPE (i)) { @@ -942,9 +942,7 @@ case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: case IMAGE_POINTER: - hash = HASH6 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), - IMAGE_INSTANCE_PIXMAP_HEIGHT (i), - IMAGE_INSTANCE_PIXMAP_DEPTH (i), + hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i), IMAGE_INSTANCE_PIXMAP_SLICE (i), internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), depth + 1)); @@ -955,18 +953,17 @@ internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1), internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1)); - case IMAGE_LAYOUT: - if (IMAGE_INSTANCE_TYPE (i) == IMAGE_LAYOUT) - hash = HASH3 (hash, - internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1), - internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i), - depth + 1)); case IMAGE_SUBWINDOW: - hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i), - IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i), - (int) IMAGE_INSTANCE_SUBWINDOW_ID (i)); + hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i)); break; + case IMAGE_LAYOUT: + hash = HASH3 (hash, + internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1), + internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i), + depth + 1)); + break; + default: abort (); } @@ -982,7 +979,7 @@ struct Lisp_Image_Instance); static Lisp_Object -allocate_image_instance (Lisp_Object device) +allocate_image_instance (Lisp_Object device, Lisp_Object glyph) { struct Lisp_Image_Instance *lp = alloc_lcrecord_type (struct Lisp_Image_Instance, &lrecord_image_instance); @@ -994,7 +991,12 @@ lp->name = Qnil; lp->x_offset = 0; lp->y_offset = 0; + lp->width = 0; + lp->height = 0; + lp->glyph = glyph; + MARK_IMAGE_INSTANCE_CHANGED (lp); /* So that layouts get done. */ XSETIMAGE_INSTANCE (val, lp); + MARK_GLYPHS_CHANGED; /* So that the dirty flag gets reset. */ return val; } @@ -1176,7 +1178,7 @@ if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit)) signal_simple_error ("Inheritance not allowed here", data); ii = instantiate_image_instantiator (device, device, data, - Qnil, Qnil, dest_mask); + Qnil, Qnil, dest_mask, Qnil); RETURN_UNGCPRO (ii); } @@ -1450,12 +1452,10 @@ case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: case IMAGE_POINTER: - return make_int (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance)); - case IMAGE_SUBWINDOW: case IMAGE_WIDGET: case IMAGE_LAYOUT: - return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance)); + return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance)); default: return Qnil; @@ -1474,12 +1474,10 @@ case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: case IMAGE_POINTER: - return make_int (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance)); - case IMAGE_SUBWINDOW: case IMAGE_WIDGET: case IMAGE_LAYOUT: - return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance)); + return make_int (XIMAGE_INSTANCE_WIDTH (image_instance)); default: return Qnil; @@ -1611,7 +1609,7 @@ /* #### There should be a copy_image_instance(), which calls a device-specific method to copy the window-system subobject. */ - new = allocate_image_instance (device); + new = allocate_image_instance (device, Qnil); copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance)); /* note that if this method returns non-zero, this method MUST copy any window-system resources, so that when one image instance is @@ -1622,6 +1620,98 @@ return new; } + +/************************************************************************/ +/* Geometry calculations */ +/************************************************************************/ + +/* Find out desired geometry of the image instance. If there is no + special function then just return the width and / or height. */ +void +image_instance_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, + Lisp_Object domain) +{ + struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object type; + struct image_instantiator_methods* meths; + + type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); + meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); + + if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) + { + IIFORMAT_METH (meths, query_geometry, (image_instance, width, height, + disp, domain)); + } + else + { + if (width) + *width = IMAGE_INSTANCE_WIDTH (ii); + if (height) + *height = IMAGE_INSTANCE_HEIGHT (ii); + } +} + +/* Layout the image instance using the provided dimensions. Layout + widgets are going to do different kinds of calculations to + determine what size to give things so we could make the layout + function relatively simple to take account of that. An alternative + approach is to consider separately the two cases, one where you + don't mind what size you have (normal widgets) and one where you + want to specifiy something (layout widgets). */ +void +image_instance_layout (Lisp_Object image_instance, + unsigned int width, unsigned int height, + Lisp_Object domain) +{ + struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object type; + struct image_instantiator_methods* meths; + + type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); + meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); + + /* If geometry is unspecified then get some reasonable values for it. */ + if (width == IMAGE_UNSPECIFIED_GEOMETRY + || + height == IMAGE_UNSPECIFIED_GEOMETRY) + { + unsigned int dwidth, dheight; + + /* Get the desired geometry. */ + if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) + { + IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight, + IMAGE_DESIRED_GEOMETRY, + domain)); + } + else + { + dwidth = IMAGE_INSTANCE_WIDTH (ii); + dheight = IMAGE_INSTANCE_HEIGHT (ii); + } + + /* Compare with allowed geometry. */ + if (width == IMAGE_UNSPECIFIED_GEOMETRY) + width = dwidth; + if (height == IMAGE_UNSPECIFIED_GEOMETRY) + height = dheight; + } + + /* At this point width and height should contain sane values. Thus + we set the glyph geometry and lay it out. */ + IMAGE_INSTANCE_WIDTH (ii) = width; + IMAGE_INSTANCE_HEIGHT (ii) = height; + + if (meths && HAS_IIFORMAT_METH_P (meths, layout)) + { + IIFORMAT_METH (meths, layout, (image_instance, width, height, domain)); + } + /* else no change to the geometry. */ +} + /************************************************************************/ /* error helpers */ @@ -1718,7 +1808,7 @@ return IMAGE_TEXT_MASK; } -/* called from autodetect_instantiate() */ +/* Called from autodetect_instantiate() */ void string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, @@ -1726,8 +1816,9 @@ { Lisp_Object string = find_keyword_in_vector (instantiator, Q_data); struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - assert (!NILP (string)); + + /* Should never get here with a domain other than a window. */ + assert (!NILP (string) && WINDOWP (domain)); if (dest_mask & IMAGE_TEXT_MASK) { IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; @@ -1737,6 +1828,114 @@ incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); } +/* Sort out the size of the text that is being displayed. Calculating + it dynamically allows us to change the text and still see + everything. Note that the following methods are for text not string + since that is what the instantiated type is. The first method is a + helper that is used elsewhere for calculating text geometry. */ +void +query_string_geometry (Lisp_Object string, Lisp_Object face, + unsigned int* width, unsigned int* height, + unsigned int* descent, Lisp_Object domain) +{ + struct font_metric_info fm; + unsigned char charsets[NUM_LEADING_BYTES]; + struct face_cachel frame_cachel; + struct face_cachel *cachel; + Lisp_Object frame = FW_FRAME (domain); + + /* Compute height */ + if (height) + { + /* Compute string metric info */ + find_charsets_in_bufbyte_string (charsets, + XSTRING_DATA (string), + XSTRING_LENGTH (string)); + + /* Fallback to the default face if none was provided. */ + if (!NILP (face)) + { + reset_face_cachel (&frame_cachel); + update_face_cachel_data (&frame_cachel, frame, face); + cachel = &frame_cachel; + } + else + { + cachel = WINDOW_FACE_CACHEL (XWINDOW (domain), DEFAULT_INDEX); + } + + ensure_face_cachel_complete (cachel, domain, charsets); + face_cachel_charset_font_metric_info (cachel, charsets, &fm); + + *height = fm.ascent + fm.descent; + /* #### descent only gets set if we query the height as well. */ + if (descent) + *descent = fm.descent; + } + + /* Compute width */ + if (width) + { + if (!NILP (face)) + *width = redisplay_frame_text_width_string (XFRAME (frame), + face, + 0, string, 0, -1); + else + *width = redisplay_frame_text_width_string (XFRAME (frame), + Vdefault_face, + 0, string, 0, -1); + } +} + +Lisp_Object +query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain) +{ + unsigned char charsets[NUM_LEADING_BYTES]; + struct face_cachel frame_cachel; + struct face_cachel *cachel; + int i; + Lisp_Object frame = FW_FRAME (domain); + + /* Compute string font info */ + find_charsets_in_bufbyte_string (charsets, + XSTRING_DATA (string), + XSTRING_LENGTH (string)); + + reset_face_cachel (&frame_cachel); + update_face_cachel_data (&frame_cachel, frame, face); + cachel = &frame_cachel; + + ensure_face_cachel_complete (cachel, domain, charsets); + + for (i = 0; i < NUM_LEADING_BYTES; i++) + { + if (charsets[i]) + { + return FACE_CACHEL_FONT (cachel, + CHARSET_BY_LEADING_BYTE (i + + MIN_LEADING_BYTE)); + + } + } +} + +static void +text_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + unsigned int descent = 0; + + query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii), + IMAGE_INSTANCE_FACE (ii), + width, height, &descent, domain); + + /* The descent gets set as a side effect of querying the + geometry. */ + IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent; +} + /* set the properties of a string */ static Lisp_Object text_set_property (Lisp_Object image_instance, Lisp_Object prop, @@ -1777,20 +1976,12 @@ Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, Lisp_Object domain) { - Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); - struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - assert (!NILP (data)); /* #### implement this */ warn_when_safe (Qunimplemented, Qnotice, "`formatted-string' not yet implemented; assuming `string'"); - if (dest_mask & IMAGE_TEXT_MASK) - { - IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; - IMAGE_INSTANCE_TEXT_STRING (ii) = data; - } - else - incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); + + string_instantiate (image_instance, instantiator, + pointer_fg, pointer_bg, dest_mask, domain); } @@ -2447,6 +2638,7 @@ { Lisp_Object device = DFW_DEVICE (domain); struct device *d = XDEVICE (device); + Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier)); int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier); int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER); @@ -2569,7 +2761,8 @@ domain, instantiator, pointer_fg, pointer_bg, - dest_mask); + dest_mask, + glyph); Fsetcar (locative, instance); /* only after the image has been instantiated do we know @@ -3163,7 +3356,8 @@ break; case GLYPH_ICON: XIMAGE_SPECIFIER_ALLOWED (g->image) = - IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK; + IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK + | IMAGE_COLOR_PIXMAP_MASK; break; default: abort (); @@ -3296,70 +3490,53 @@ } } -/***************************************************************************** - glyph_width +Lisp_Object +glyph_image_instance (Lisp_Object glyph, Lisp_Object domain, + Error_behavior errb, int no_quit) +{ + Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph)); - Return the width of the given GLYPH on the given WINDOW. If the - instance is a string then the width is calculated using the font of - the given FACE, unless a face is defined by the glyph itself. - ****************************************************************************/ -unsigned short -glyph_width (Lisp_Object glyph_or_image, Lisp_Object frame_face, - face_index window_findex, Lisp_Object window) + /* This can never return Qunbound. All glyphs have 'nothing as + a fallback. */ + Lisp_Object image_instance = specifier_instance (specifier, Qunbound, + domain, errb, no_quit, 0, + Qzero); + /* Set a back pointer so that we can get at glyph attributes from + the image instance. */ + XIMAGE_INSTANCE_GLYPH (image_instance) = glyph; +} + +static Lisp_Object +glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window) { Lisp_Object instance = glyph_or_image; - Lisp_Object frame = XWINDOW (window)->frame; - /* #### We somehow need to distinguish between the user causing this - error condition and a bug causing it. */ if (GLYPHP (glyph_or_image)) instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); - - if (!IMAGE_INSTANCEP (instance)) - return 0; - - switch (XIMAGE_INSTANCE_TYPE (instance)) - { - case IMAGE_TEXT: - { - Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance); - Lisp_Object private_face = Qnil; - if (GLYPHP (glyph_or_image)) - private_face = XGLYPH_FACE(glyph_or_image); - - if (!NILP (private_face)) - return redisplay_frame_text_width_string (XFRAME (frame), - private_face, - 0, str, 0, -1); - else - if (!NILP (frame_face)) - return redisplay_frame_text_width_string (XFRAME (frame), - frame_face, - 0, str, 0, -1); - else - return redisplay_text_width_string (XWINDOW (window), - window_findex, - 0, str, 0, -1); - } + return instance; +} - case IMAGE_MONO_PIXMAP: - case IMAGE_COLOR_PIXMAP: - case IMAGE_POINTER: - return XIMAGE_INSTANCE_PIXMAP_WIDTH (instance); +/***************************************************************************** + glyph_width - case IMAGE_NOTHING: - return 0; + Return the width of the given GLYPH on the given WINDOW. + Calculations are done based on recursively querying the geometry of + the associated image instances. + ****************************************************************************/ +unsigned short +glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain) +{ + Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, + domain); + if (!IMAGE_INSTANCEP (instance)) + return 0; - case IMAGE_SUBWINDOW: - case IMAGE_WIDGET: - case IMAGE_LAYOUT: - return XIMAGE_INSTANCE_SUBWINDOW_WIDTH (instance); + if (XIMAGE_INSTANCE_DIRTYP (instance)) + image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, + IMAGE_UNSPECIFIED_GEOMETRY, domain); - default: - abort (); - return 0; - } + return XIMAGE_INSTANCE_WIDTH (instance); } DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /* @@ -3372,126 +3549,60 @@ XSETWINDOW (window, decode_window (window)); CHECK_GLYPH (glyph); - return make_int (glyph_width (glyph, Qnil, DEFAULT_INDEX, window)); + return make_int (glyph_width (glyph, window)); } - -#define RETURN_ASCENT 0 -#define RETURN_DESCENT 1 -#define RETURN_HEIGHT 2 -Lisp_Object -glyph_image_instance (Lisp_Object glyph, Lisp_Object domain, - Error_behavior errb, int no_quit) -{ - Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph)); - - /* This can never return Qunbound. All glyphs have 'nothing as - a fallback. */ - return specifier_instance (specifier, Qunbound, domain, errb, no_quit, 0, - Qzero); -} - -static unsigned short -glyph_height_internal (Lisp_Object glyph_or_image, Lisp_Object frame_face, - face_index window_findex, Lisp_Object window, - int function) +unsigned short +glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain) { - Lisp_Object instance = glyph_or_image; - Lisp_Object frame = XWINDOW (window)->frame; - - if (GLYPHP (glyph_or_image)) - instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); - + Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, + domain); if (!IMAGE_INSTANCEP (instance)) return 0; - - switch (XIMAGE_INSTANCE_TYPE (instance)) - { - case IMAGE_TEXT: - { - struct font_metric_info fm; - Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); - unsigned char charsets[NUM_LEADING_BYTES]; - struct face_cachel frame_cachel; - struct face_cachel *cachel; - - find_charsets_in_bufbyte_string (charsets, - XSTRING_DATA (string), - XSTRING_LENGTH (string)); - - if (!NILP (frame_face)) - { - reset_face_cachel (&frame_cachel); - update_face_cachel_data (&frame_cachel, frame, frame_face); - cachel = &frame_cachel; - } - else - cachel = WINDOW_FACE_CACHEL (XWINDOW (window), window_findex); - ensure_face_cachel_complete (cachel, window, charsets); - - face_cachel_charset_font_metric_info (cachel, charsets, &fm); - - switch (function) - { - case RETURN_ASCENT: return fm.ascent; - case RETURN_DESCENT: return fm.descent; - case RETURN_HEIGHT: return fm.ascent + fm.descent; - default: - abort (); - return 0; /* not reached */ - } - } - - case IMAGE_MONO_PIXMAP: - case IMAGE_COLOR_PIXMAP: - case IMAGE_POINTER: - /* #### Ugh ugh ugh -- temporary crap */ - if (function == RETURN_ASCENT || function == RETURN_HEIGHT) - return XIMAGE_INSTANCE_PIXMAP_HEIGHT (instance); - else - return 0; - case IMAGE_NOTHING: - return 0; + if (XIMAGE_INSTANCE_DIRTYP (instance)) + image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, + IMAGE_UNSPECIFIED_GEOMETRY, domain); - case IMAGE_SUBWINDOW: - case IMAGE_WIDGET: - case IMAGE_LAYOUT: - /* #### Ugh ugh ugh -- temporary crap */ - if (function == RETURN_ASCENT || function == RETURN_HEIGHT) - return XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (instance); - else - return 0; - - default: - abort (); - return 0; - } + if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT) + return XIMAGE_INSTANCE_TEXT_ASCENT (instance); + else + return XIMAGE_INSTANCE_HEIGHT (instance); } unsigned short -glyph_ascent (Lisp_Object glyph, Lisp_Object frame_face, - face_index window_findex, Lisp_Object window) +glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain) { - return glyph_height_internal (glyph, frame_face, window_findex, window, - RETURN_ASCENT); -} + Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, + domain); + if (!IMAGE_INSTANCEP (instance)) + return 0; -unsigned short -glyph_descent (Lisp_Object glyph, Lisp_Object frame_face, - face_index window_findex, Lisp_Object window) -{ - return glyph_height_internal (glyph, frame_face, window_findex, window, - RETURN_DESCENT); + if (XIMAGE_INSTANCE_DIRTYP (instance)) + image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, + IMAGE_UNSPECIFIED_GEOMETRY, domain); + + if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT) + return XIMAGE_INSTANCE_TEXT_DESCENT (instance); + else + return 0; } /* strictly a convenience function. */ unsigned short -glyph_height (Lisp_Object glyph, Lisp_Object frame_face, - face_index window_findex, Lisp_Object window) +glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain) { - return glyph_height_internal (glyph, frame_face, window_findex, window, - RETURN_HEIGHT); + Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, + domain); + + if (!IMAGE_INSTANCEP (instance)) + return 0; + + if (XIMAGE_INSTANCE_DIRTYP (instance)) + image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, + IMAGE_UNSPECIFIED_GEOMETRY, domain); + + return XIMAGE_INSTANCE_HEIGHT (instance); } DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /* @@ -3504,7 +3615,7 @@ XSETWINDOW (window, decode_window (window)); CHECK_GLYPH (glyph); - return make_int (glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window)); + return make_int (glyph_ascent (glyph, window)); } DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /* @@ -3517,7 +3628,7 @@ XSETWINDOW (window, decode_window (window)); CHECK_GLYPH (glyph); - return make_int (glyph_descent (glyph, Qnil, DEFAULT_INDEX, window)); + return make_int (glyph_descent (glyph, window)); } /* This is redundant but I bet a lot of people expect it to exist. */ @@ -3531,22 +3642,14 @@ XSETWINDOW (window, decode_window (window)); CHECK_GLYPH (glyph); - return make_int (glyph_height (glyph, Qnil, DEFAULT_INDEX, window)); + return make_int (glyph_height (glyph, window)); } -#undef RETURN_ASCENT -#undef RETURN_DESCENT -#undef RETURN_HEIGHT - static unsigned int glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window) { - Lisp_Object instance = glyph_or_image; - - if (GLYPHP (glyph_or_image)) - instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); - - return XIMAGE_INSTANCE_DIRTYP (instance); + return XIMAGE_INSTANCE_DIRTYP (glyph_image_instance_maybe + (glyph_or_image, window)); } static void @@ -3621,6 +3724,31 @@ (XGLYPH (glyph)->after_change) (glyph, property, locale); } +static void +glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, Lisp_Object domain) +{ + Lisp_Object instance = glyph_or_image; + + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); + + image_instance_query_geometry (instance, width, height, disp, domain); +} + +static void +glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window, + unsigned int width, unsigned int height, Lisp_Object domain) +{ + Lisp_Object instance = glyph_or_image; + + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); + + image_instance_layout (instance, width, height, domain); +} + /***************************************************************************** * glyph cachel functions * @@ -3662,9 +3790,9 @@ and passing it to the size functions. */ instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window); - cachel->width = glyph_width (instance, Qnil, DEFAULT_INDEX, window); - cachel->ascent = glyph_ascent (instance, Qnil, DEFAULT_INDEX, window); - cachel->descent = glyph_descent (instance, Qnil, DEFAULT_INDEX, window); + cachel->width = glyph_width (instance, window); + cachel->ascent = glyph_ascent (instance, window); + cachel->descent = glyph_descent (instance, window); } cachel->updated = 1; @@ -3781,7 +3909,7 @@ /***************************************************************************** * subwindow cachel functions * *****************************************************************************/ -/* subwindows are curious in that you have to physically unmap them to +/* Subwindows are curious in that you have to physically unmap them to not display them. It is problematic deciding what to do in redisplay. We have two caches - a per-window instance cache that keeps track of subwindows on a window, these are linked to their @@ -4051,8 +4179,15 @@ return; MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii)); + /* We must update the window's size as it may have been changed by + the the layout routines. We also do this here so that explicit resizing + from lisp does not result in synchronous updates. */ + MAYBE_DEVMETH (XDEVICE (ii->device), resize_subwindow, (ii, + IMAGE_INSTANCE_WIDTH (ii), + IMAGE_INSTANCE_HEIGHT (ii))); } +/* Update all the subwindows on a frame. */ void update_frame_subwindows (struct frame *f) { @@ -4133,6 +4268,15 @@ cachel->height = dga->height; cachel->being_displayed = 1; + /* This forces any pending display changes to happen to the image + before we show it. I'm not sure whether or not we need mark as + clean here, but for now we will. */ + if (IMAGE_INSTANCE_DIRTYP (ii)) + { + update_subwindow (subwindow); + IMAGE_INSTANCE_DIRTYP (ii) = 0; + } + MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y, dga)); } @@ -4165,7 +4309,10 @@ IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame; - /* this stuff may get overidden by the widget code */ + /* #### This stuff may get overidden by the widget code and is + actually really dumb now that we have dynamic geometry + calculations. What should really happen is that the subwindow + should query its child for and appropriate geometry. */ if (NILP (width)) IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20; else @@ -4217,21 +4364,19 @@ CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); if (NILP (width)) - neww = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); + neww = XIMAGE_INSTANCE_WIDTH (subwindow); else neww = XINT (width); if (NILP (height)) - newh = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); + newh = XIMAGE_INSTANCE_HEIGHT (subwindow); else newh = XINT (height); - - - MAYBE_DEVMETH (XDEVICE (XIMAGE_INSTANCE_DEVICE (subwindow)), - resize_subwindow, (XIMAGE_INSTANCE (subwindow), neww, newh)); - XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow) = newh; - XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow) = neww; + /* The actual resizing gets done asychronously by + update_subwindow. */ + XIMAGE_INSTANCE_HEIGHT (subwindow) = newh; + XIMAGE_INSTANCE_WIDTH (subwindow) = neww; /* need to update the cachels as redisplay will not do this */ update_subwindow_cachel (subwindow); @@ -4370,7 +4515,7 @@ also might not. */ MARK_DEVICE_FRAMES_GLYPHS_CHANGED (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))); - IMAGE_INSTANCE_DIRTYP (ii) = 1; + MARK_IMAGE_INSTANCE_CHANGED (ii); } } } @@ -4645,6 +4790,7 @@ /* Do this so we can set strings. */ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text"); IIFORMAT_HAS_METHOD (text, set_property); + IIFORMAT_HAS_METHOD (text, query_geometry); INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string"); Index: src/glyphs.h =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.h,v retrieving revision 1.18.2.23 diff -u -r1.18.2.23 glyphs.h --- src/glyphs.h 1999/12/21 17:37:46 1.18.2.23 +++ src/glyphs.h 2000/01/08 20:12:59 @@ -84,6 +84,18 @@ extern const struct struct_description iim_description; +enum image_instance_geometry +{ + IMAGE_GEOMETRY, + IMAGE_DESIRED_GEOMETRY, + IMAGE_MIN_GEOMETRY, + IMAGE_MAX_GEOMETRY, + IMAGE_UNSPECIFIED_GEOMETRY = ~0 +}; + +#define WIDGET_BORDER_HEIGHT 4 +#define WIDGET_BORDER_WIDTH 4 + struct image_instantiator_methods { Lisp_Object symbol; @@ -132,12 +144,19 @@ Lisp_Object property, Lisp_Object val); - /* Find out the geometry of this image instance. */ + /* Find out the desired geometry, as given by disp, of this image + instance. Actual geometry is stored in the appropriate slots in the + image instance. */ void (*query_geometry_method) (Lisp_Object image_instance, - int* width, int* height, int disp); - - /* Layout the instances children. */ - void (*layout_children_method) (Lisp_Object image_instance); + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, + Lisp_Object domain); + + /* Layout the instance and its children bounded by the provided + dimensions. */ + void (*layout_method) (Lisp_Object image_instance, + unsigned int width, unsigned int height, + Lisp_Object domain); }; /***** Calling an image-instantiator method *****/ @@ -306,10 +325,16 @@ void subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, Lisp_Object domain); -void widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain, int default_textheight, - int default_pixheight, int default_textwidth); +void widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain); +void image_instance_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, + Lisp_Object domain); +void image_instance_layout (Lisp_Object image_instance, + unsigned int width, unsigned int height, + Lisp_Object domain); DECLARE_DOESNT_RETURN (incompatible_image_types (Lisp_Object instantiator, int given_dest_mask, @@ -372,14 +397,6 @@ IMAGE_LAYOUT }; -enum image_instance_geometry -{ - IMAGE_GEOMETRY, - IMAGE_DESIRED_GEOMETRY, - IMAGE_MIN_GEOMETRY, - IMAGE_MAX_GEOMETRY -}; - #define IMAGE_NOTHING_MASK (1 << 0) #define IMAGE_TEXT_MASK (1 << 1) #define IMAGE_MONO_PIXMAP_MASK (1 << 2) @@ -463,6 +480,9 @@ struct lcrecord_header header; Lisp_Object device; Lisp_Object name; + /* The glyph from which we were instantiated. This is a weak + reference. */ + Lisp_Object glyph; enum image_instance_type type; unsigned int x_offset, y_offset; /* for layout purposes */ unsigned int width, height; @@ -493,11 +513,17 @@ Lisp_Object frame; void* subwindow; /* specific devices can use this as necessary */ unsigned int being_displayed : 1; /* used to detect when needs to be unmapped */ + unsigned int v_resize : 1; /* Whether the vsize is allowed to change. */ + unsigned int h_resize : 1; /* Whether the hsize is allowed to change. */ union { struct { - Lisp_Object face; /* foreground and background colors */ + /* Face for colors and font. We specify this here becuase we + want people to be able to put :face in the instantiator + spec. Using gyph-face is more inconvenient, although more + general. */ + Lisp_Object face; Lisp_Object type; Lisp_Object props; /* properties */ Lisp_Object gui_item; /* a list of gui_items */ @@ -506,6 +532,8 @@ { Lisp_Object children; /* managed children */ Lisp_Object border; /* Style of enclosing border or text. */ + unsigned int orientation : 1; /* Vertical or horizontal. */ + unsigned int justification : 2; /* Left, right or center. */ } layout; } s; } subwindow; @@ -515,8 +543,18 @@ void *data; }; +/* Layout bit-fields. */ +#define LAYOUT_HORIZONTAL 0 +#define LAYOUT_VERTICAL 1 + +#define LAYOUT_JUSTIFY_LEFT 0 +#define LAYOUT_JUSTIFY_RIGHT 1 +#define LAYOUT_JUSTIFY_CENTER 2 + +/* Accessor macros. */ #define IMAGE_INSTANCE_DEVICE(i) ((i)->device) #define IMAGE_INSTANCE_NAME(i) ((i)->name) +#define IMAGE_INSTANCE_GLYPH(i) ((i)->glyph) #define IMAGE_INSTANCE_TYPE(i) ((i)->type) #define IMAGE_INSTANCE_XOFFSET(i) ((i)->x_offset) #define IMAGE_INSTANCE_YOFFSET(i) ((i)->y_offset) @@ -526,6 +564,8 @@ ((IMAGE_INSTANCE_TYPE (i) == IMAGE_MONO_PIXMAP) \ || (IMAGE_INSTANCE_TYPE (i) == IMAGE_COLOR_PIXMAP)) #define IMAGE_INSTANCE_DIRTYP(i) ((i)->dirty) +#define IMAGE_INSTANCE_FACE(i) \ + XGLYPH_FACE (IMAGE_INSTANCE_GLYPH (i)) #define IMAGE_INSTANCE_TEXT_STRING(i) ((i)->u.text.string) #define IMAGE_INSTANCE_TEXT_WIDTH(i) \ @@ -533,6 +573,8 @@ #define IMAGE_INSTANCE_TEXT_HEIGHT(i) \ IMAGE_INSTANCE_HEIGHT(i) #define IMAGE_INSTANCE_TEXT_DESCENT(i) ((i)->u.text.descent) +#define IMAGE_INSTANCE_TEXT_ASCENT(i) \ + (IMAGE_INSTANCE_TEXT_HEIGHT(i) - IMAGE_INSTANCE_TEXT_DESCENT(i)) #define IMAGE_INSTANCE_PIXMAP_WIDTH(i) \ IMAGE_INSTANCE_WIDTH(i) @@ -559,6 +601,10 @@ #define IMAGE_INSTANCE_SUBWINDOW_FRAME(i) ((i)->u.subwindow.frame) #define IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(i) \ ((i)->u.subwindow.being_displayed) +#define IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP(i) \ +((i)->u.subwindow.v_resize) +#define IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP(i) \ +((i)->u.subwindow.h_resize) #define IMAGE_INSTANCE_WIDGET_WIDTH(i) \ IMAGE_INSTANCE_WIDTH(i) @@ -566,7 +612,12 @@ IMAGE_INSTANCE_HEIGHT(i) #define IMAGE_INSTANCE_WIDGET_TYPE(i) ((i)->u.subwindow.s.widget.type) #define IMAGE_INSTANCE_WIDGET_PROPS(i) ((i)->u.subwindow.s.widget.props) -#define IMAGE_INSTANCE_WIDGET_FACE(i) ((i)->u.subwindow.s.widget.face) +#define SET_IMAGE_INSTANCE_WIDGET_FACE(i,f) \ + ((i)->u.subwindow.s.widget.face = f) +#define IMAGE_INSTANCE_WIDGET_FACE(i) \ + (!NILP ((i)->u.subwindow.s.widget.face) ? (i)->u.subwindow.s.widget.face : \ + !NILP (IMAGE_INSTANCE_FACE (i)) ? IMAGE_INSTANCE_FACE (i) : \ + Vwidget_face) #define IMAGE_INSTANCE_WIDGET_ITEMS(i) ((i)->u.subwindow.s.widget.gui_item) #define IMAGE_INSTANCE_WIDGET_ITEM(i) \ (CONSP (IMAGE_INSTANCE_WIDGET_ITEMS (i)) ? \ @@ -581,6 +632,8 @@ IMAGE_INSTANCE_DEVICE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_NAME(i) \ IMAGE_INSTANCE_NAME (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_GLYPH(i) \ + IMAGE_INSTANCE_GLYPH (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_TYPE(i) \ IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_XOFFSET(i) \ @@ -589,9 +642,23 @@ IMAGE_INSTANCE_YOFFSET (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_DIRTYP(i) \ IMAGE_INSTANCE_DIRTYP (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_WIDTH(i) \ + IMAGE_INSTANCE_WIDTH (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_HEIGHT(i) \ + IMAGE_INSTANCE_HEIGHT (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_FACE(i) \ + IMAGE_INSTANCE_FACE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_TEXT_STRING(i) \ IMAGE_INSTANCE_TEXT_STRING (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_TEXT_WIDTH(i) \ + IMAGE_INSTANCE_TEXT_WIDTH (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_TEXT_HEIGHT(i) \ + IMAGE_INSTANCE_TEXT_HEIGHT (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_TEXT_ASCENT(i) \ + IMAGE_INSTANCE_TEXT_ASCENT (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_TEXT_DESCENT(i) \ + IMAGE_INSTANCE_TEXT_DESCENT (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_PIXMAP_WIDTH(i) \ IMAGE_INSTANCE_PIXMAP_WIDTH (XIMAGE_INSTANCE (i)) @@ -630,6 +697,8 @@ IMAGE_INSTANCE_WIDGET_PROPS (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_FACE(i) \ IMAGE_INSTANCE_WIDGET_FACE (XIMAGE_INSTANCE (i)) +#define XSET_IMAGE_INSTANCE_WIDGET_FACE(i) \ + SET_IMAGE_INSTANCE_WIDGET_FACE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_ITEM(i) \ IMAGE_INSTANCE_WIDGET_ITEM (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_ITEMS(i) \ @@ -758,19 +827,10 @@ extern Lisp_Object Vinvisible_text_glyph, Voctal_escape_glyph, Vtruncation_glyph; extern Lisp_Object Vxemacs_logo; -unsigned short glyph_width (Lisp_Object glyph, Lisp_Object frame_face, - face_index window_findex, - Lisp_Object window); -unsigned short glyph_ascent (Lisp_Object glyph, Lisp_Object frame_face, - face_index window_findex, - Lisp_Object window); -unsigned short glyph_descent (Lisp_Object glyph, - Lisp_Object frame_face, - face_index window_findex, - Lisp_Object window); -unsigned short glyph_height (Lisp_Object glyph, Lisp_Object frame_face, - face_index window_findex, - Lisp_Object window); +unsigned short glyph_width (Lisp_Object glyph, Lisp_Object domain); +unsigned short glyph_ascent (Lisp_Object glyph, Lisp_Object domain); +unsigned short glyph_descent (Lisp_Object glyph, Lisp_Object domain); +unsigned short glyph_height (Lisp_Object glyph, Lisp_Object domain); Lisp_Object glyph_baseline (Lisp_Object glyph, Lisp_Object domain); Lisp_Object glyph_face (Lisp_Object glyph, Lisp_Object domain); int glyph_contrib_p (Lisp_Object glyph, Lisp_Object domain); @@ -789,11 +849,11 @@ void (*after_change) (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale)); -Lisp_Object widget_face_font_info (Lisp_Object domain, Lisp_Object face, - int *height, int *width); -void widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face, - int th, int tw, - int* height, int* width); +void query_string_geometry ( Lisp_Object string, Lisp_Object face, + unsigned int* width, unsigned int* height, + unsigned int* descent, Lisp_Object domain); +Lisp_Object query_string_font (Lisp_Object string, + Lisp_Object face, Lisp_Object domain); Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object device); void disable_glyph_animated_timeout (int i); @@ -868,8 +928,8 @@ struct subwindow_cachel { Lisp_Object subwindow; - int x, y; - int width, height; + unsigned int x, y; + unsigned int width, height; unsigned int being_displayed : 1; unsigned int updated : 1; }; @@ -890,10 +950,8 @@ struct expose_ignore { - int x; - int y; - int width; - int height; + unsigned int x, y; + unsigned int width, height; struct expose_ignore *next; }; Index: src/redisplay-output.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay-output.c,v retrieving revision 1.11.2.22 diff -u -r1.11.2.22 redisplay-output.c --- src/redisplay-output.c 1999/12/23 02:50:45 1.11.2.22 +++ src/redisplay-output.c 2000/01/08 20:13:06 @@ -1234,8 +1234,8 @@ XSETWINDOW (window, w); - layout_height = glyph_height (image_instance, Qnil, findex, window); - layout_width = glyph_width (image_instance, Qnil, findex, window); + layout_height = glyph_height (image_instance, window); + layout_width = glyph_width (image_instance, window); dga->height = layout_height; dga->width = layout_width; @@ -1319,8 +1319,8 @@ struct display_glyph_area cdga; cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset; cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset; - cdga.width = glyph_width (child, Qnil, findex, window); - cdga.height = glyph_height (child, Qnil, findex, window); + cdga.width = glyph_width (child, window); + cdga.height = glyph_height (child, window); /* Although normalization is done by the output routines we have to do it here so that they don't try and @@ -1362,9 +1362,9 @@ xzero (dl); /* Munge boxes into display lines. */ dl.ypos = (cdb.ypos - cdga.yoffset) - + glyph_ascent (child, Qnil, findex, window); - dl.ascent = glyph_ascent (child, Qnil, findex, window); - dl.descent = glyph_descent (child, Qnil, findex, window); + + glyph_ascent (child, window); + dl.ascent = glyph_ascent (child, window); + dl.descent = glyph_descent (child, window); dl.top_clip = cdga.yoffset; dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height); /* output_string doesn't understand offsets in Index: src/redisplay.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/redisplay.c,v retrieving revision 1.55.2.29 diff -u -r1.55.2.29 redisplay.c --- src/redisplay.c 2000/01/04 08:50:26 1.55.2.29 +++ src/redisplay.c 2000/01/08 20:13:34 @@ -1541,7 +1541,7 @@ if (cachel) width = cachel->width; else - width = glyph_width (gb->glyph, Qnil, data->findex, data->window); + width = glyph_width (gb->glyph, data->window); if (!width) return NULL; @@ -1604,9 +1604,8 @@ } else { - ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window); - descent = glyph_descent (gb->glyph, Qnil, data->findex, - data->window); + ascent = glyph_ascent (gb->glyph, data->window); + descent = glyph_descent (gb->glyph, data->window); } baseline = glyph_baseline (gb->glyph, data->window); @@ -2767,8 +2766,8 @@ unsigned short ascent, descent; Lisp_Object baseline = glyph_baseline (gb->glyph, window); - ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window); - descent = glyph_descent (gb->glyph, Qnil, gb->findex, window); + ascent = glyph_ascent (gb->glyph, window); + descent = glyph_descent (gb->glyph, window); /* A pixmap that has not had a baseline explicitly set. We use the existing ascent / descent ratio of the @@ -2882,7 +2881,7 @@ { int width; - width = glyph_width (gb->glyph, Qnil, gb->findex, window); + width = glyph_width (gb->glyph, window); if (white_in_start - width >= left_in_end) { @@ -2933,7 +2932,7 @@ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); + gb->width = glyph_width (gb->glyph, window); used_in += gb->width; Dynarr_add (ib, *gb); } @@ -3002,7 +3001,7 @@ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (used_out) { @@ -3044,7 +3043,7 @@ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (out_end + width <= in_out_start) { @@ -3201,7 +3200,7 @@ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (white_in_end + width <= dl->bounds.right_in) { @@ -3251,7 +3250,7 @@ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); + gb->width = glyph_width (gb->glyph, window); used_in += gb->width; Dynarr_add (ib, *gb); } @@ -3315,7 +3314,7 @@ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (used_out) { @@ -3356,7 +3355,7 @@ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (out_start - width >= in_out_end) { @@ -6189,7 +6188,9 @@ somewhere else once tty updates occur on a per-frame basis. */ mark_face_cachels_as_clean (w); - /* The glyph cachels only get dirty if someone changed something. */ + /* The glyph cachels only get dirty if someone changed something. + Since redisplay has now effectively ended we can reset the dirty + flag since everything must be up-to-date. */ if (glyphs_changed) mark_glyph_cachels_as_clean (w); Index: src/toolbar-x.c =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/src/toolbar-x.c,v retrieving revision 1.12.2.3 diff -u -r1.12.2.3 toolbar-x.c --- src/toolbar-x.c 1999/08/24 08:38:45 1.12.2.3 +++ src/toolbar-x.c 2000/01/08 20:13:37 @@ -296,9 +296,9 @@ return XINT (f->toolbar_size[pos]); if (vert) - size = glyph_height (glyph, Vdefault_face, 0, window); + size = glyph_height (glyph, window); else - size = glyph_width (glyph, Vdefault_face, 0, window); + size = glyph_width (glyph, window); } if (!size) Index: tests/glyph-test.el =================================================================== RCS file: /usr/CVSroot/XEmacs/xemacs/tests/Attic/glyph-test.el,v retrieving revision 1.1.2.15 diff -u -r1.1.2.15 glyph-test.el --- tests/glyph-test.el 1999/12/21 17:37:50 1.1.2.15 +++ tests/glyph-test.el 2000/01/08 20:13:38 @@ -2,6 +2,10 @@ (make-extent (point) (point)) (setq im (make-glyph [xpm :file "xemacs-icon.xpm"]))) +(set-extent-begin-glyph + (make-extent (point) (point)) + (make-glyph [string :data "xemacs"])) + (defun foo () (interactive) (setq ok-select (not ok-select))) @@ -104,7 +108,8 @@ ;; normal pushbutton (set-extent-begin-glyph (make-extent (point) (point)) - (make-glyph [button :descriptor ["A Big Button" foo ]])) + (setq pbutton + (make-glyph [button :descriptor ["A Big Button" foo ]]))) ;; edit box (set-extent-begin-glyph