X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fglyphs-msw.c;h=72902aa3ea00d669311306feb43284b66251cce5;hb=5d0cf827247def2db200614bf5d3ab700776d641;hp=4cd61ab8b6fe3a024f40948c66146255ba7eaf05;hpb=2fd9701a4f902054649dde9143a3f77809afee8f;p=chise%2Fxemacs-chise.git.1 diff --git a/src/glyphs-msw.c b/src/glyphs-msw.c index 4cd61ab..72902aa 100644 --- a/src/glyphs-msw.c +++ b/src/glyphs-msw.c @@ -20,7 +20,7 @@ Boston, MA 02111-1307, USA. */ /* Synched up with: Not in FSF. */ -/* written by Andy Piper plagerising bits from +/* written by Andy Piper plagiarising bits from glyphs-x.c */ #include @@ -57,7 +57,6 @@ DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); -DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); #ifdef HAVE_JPEG DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); #endif @@ -80,6 +79,8 @@ DEFINE_DEVICE_IIFORMAT (msprinter, xbm); DEFINE_DEVICE_IIFORMAT (mswindows, xface); DEFINE_DEVICE_IIFORMAT (msprinter, xface); #endif +DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); +DEFINE_DEVICE_IIFORMAT (mswindows, native_layout); DEFINE_DEVICE_IIFORMAT (mswindows, button); DEFINE_DEVICE_IIFORMAT (mswindows, edit_field); DEFINE_DEVICE_IIFORMAT (mswindows, subwindow); @@ -121,6 +122,41 @@ get_device_compdc (struct device *d) return DEVICE_MSPRINTER_HCDC (d); } +/* + * Initialize image instance pixel sizes in II. For a display bitmap, + * these will be same as real bitmap sizes. For a printer bitmap, + * these will be scaled up so that the bitmap is proportionally enlarged + * when output to printer. Redisplay code takes care of scaling, to + * conserve memory we do not really scale bitmaps. Set the watermark + * only here. + * #### Add support for unscalable bitmaps. + */ +static void init_image_instance_geometry (Lisp_Image_Instance *ii) +{ + struct device *d = DOMAIN_XDEVICE (ii->domain); + + if (/* #### Scaleable && */ DEVICE_MSPRINTER_P (d)) + { + HDC printer_dc = DEVICE_MSPRINTER_HCDC (d); + HDC display_dc = CreateCompatibleDC (NULL); + IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = + MulDiv (IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii), + GetDeviceCaps (printer_dc, LOGPIXELSX), + GetDeviceCaps (display_dc, LOGPIXELSX)); + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = + MulDiv (IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii), + GetDeviceCaps (printer_dc, LOGPIXELSY), + GetDeviceCaps (display_dc, LOGPIXELSY)); + } + else + { + IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = + IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii); + IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = + IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii); + } +} + #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3))) /************************************************************************/ @@ -313,8 +349,7 @@ init_image_instance_from_dibitmap (Lisp_Image_Instance *ii, int x_hot, int y_hot, int create_mask) { - Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); - struct device *d = XDEVICE (device); + struct device *d = XDEVICE (IMAGE_INSTANCE_DEVICE (ii)); void* bmp_buf=0; enum image_instance_type type; HBITMAP bitmap; @@ -350,11 +385,14 @@ init_image_instance_from_dibitmap (Lisp_Image_Instance *ii, IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap; IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL; - IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = bmp_info->bmiHeader.biWidth; - IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = bmp_info->bmiHeader.biHeight; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii) = + bmp_info->bmiHeader.biWidth; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii) = + bmp_info->bmiHeader.biHeight; IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = bmp_info->bmiHeader.biBitCount; XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), x_hot); XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), y_hot); + init_image_instance_geometry (ii); if (create_mask) { @@ -469,15 +507,15 @@ mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image, BITMAPINFO *bmp_info = (BITMAPINFO*) xmalloc_and_zero (sizeof (BITMAPINFO) + sizeof (RGBQUAD)); int i, j; - int height = IMAGE_INSTANCE_PIXMAP_HEIGHT (image); + int height = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (image); - int maskbpline = BPLINE ((IMAGE_INSTANCE_PIXMAP_WIDTH (image) + 7) / 8); - int bpline = BPLINE (IMAGE_INSTANCE_PIXMAP_WIDTH (image) * 3); + int maskbpline = BPLINE ((IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image) + 7) / 8); + int bpline = BPLINE (IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image) * 3); if (!bmp_info) return; - bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image); + bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image); bmp_info->bmiHeader.biHeight = height; bmp_info->bmiHeader.biPlanes = 1; bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); @@ -509,10 +547,10 @@ mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image, /* build up an in-memory set of bits to mess with */ xzero (*bmp_info); - bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image); + bmp_info->bmiHeader.biWidth = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image); bmp_info->bmiHeader.biHeight = -height; bmp_info->bmiHeader.biPlanes = 1; - bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + bmp_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmp_info->bmiHeader.biBitCount = 24; bmp_info->bmiHeader.biCompression = BI_RGB; bmp_info->bmiHeader.biClrUsed = 0; @@ -534,7 +572,7 @@ mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image, /* now set the colored bits in the mask and transparent ones to black in the original */ - for (i=0; i> 4]); + ((flip_table[bite & 0xf] << 4) + flip_table[bite >> 4]); } } @@ -1762,11 +1825,13 @@ init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii, IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); - IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; - IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii) = width; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii) = height; IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1; XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0); XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0); + init_image_instance_geometry (ii); + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = mask ? mask : xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, TRUE, black, white); @@ -1838,7 +1903,7 @@ init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii, break; default: - abort (); + ABORT (); } } @@ -1912,6 +1977,9 @@ mswindows_xbm_instantiate (Lisp_Object image_instance, #ifdef __cplusplus extern "C" { #endif +#ifndef __STDC__ /* Needed to avoid prototype warnings */ +#define __STDC__ +#endif #include #ifdef __cplusplus } @@ -2026,13 +2094,21 @@ extern int debug_widget_instances; #endif static void +finalize_destroy_window (void *win) +{ + DestroyWindow ((HWND) win); +} + +static void mswindows_finalize_image_instance (Lisp_Image_Instance *p) { - if (DEVICE_LIVE_P (XDEVICE (p->device))) + if (!p->data) + return; + + if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))) { - if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET - || - IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) + if (image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (p)) + & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK)) { #ifdef DEBUG_WIDGETS debug_widget_instances--; @@ -2040,8 +2116,14 @@ mswindows_finalize_image_instance (Lisp_Image_Instance *p) #endif if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) { - DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)); - DestroyWindow (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)); + /* DestroyWindow is not safe here, as it will send messages + to our window proc. */ + register_post_gc_action + (finalize_destroy_window, + (void *) (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p))); + register_post_gc_action + (finalize_destroy_window, + (void *) (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p))); IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; } } @@ -2095,6 +2177,16 @@ mswindows_widget_hfont (Lisp_Image_Instance *p, return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike); } +static HDWP +begin_defer_window_pos (struct frame *f) +{ +#ifdef DEFER_WINDOW_POS + if (FRAME_MSWINDOWS_DATA (f)->hdwp == 0) + FRAME_MSWINDOWS_DATA (f)->hdwp = BeginDeferWindowPos (10); +#endif + return FRAME_MSWINDOWS_DATA (f)->hdwp; +} + /* unmap the image if it is a widget. This is used by redisplay via redisplay_unmap_subwindows */ static void @@ -2102,11 +2194,34 @@ mswindows_unmap_subwindow (Lisp_Image_Instance *p) { if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) { +#ifdef DEFER_WINDOW_POS + struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p)); + HDWP hdwp = begin_defer_window_pos (f); + HDWP new_hdwp; + new_hdwp = DeferWindowPos (hdwp, IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, + 0, 0, 0, 0, + SWP_HIDEWINDOW | SWP_NOACTIVATE | + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER + /* Setting this flag causes the call to + DeferWindowPos to fail with + "Invalid parameter". I don't understand + why we bother to try and set this + anyway. -- ben */ + /* | SWP_NOSENDCHANGING */ + ); + if (!new_hdwp) + mswindows_output_last_error ("unmapping"); + else + hdwp = new_hdwp; + FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp; +#else SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), NULL, 0, 0, 0, 0, - SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE - | SWP_NOSENDCHANGING); + SWP_HIDEWINDOW | SWP_NOACTIVATE | + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER ); +#endif if (GetFocus() == WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)) SetFocus (GetParent (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p))); } @@ -2118,6 +2233,11 @@ static void mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y, struct display_glyph_area* dga) { +#ifdef DEFER_WINDOW_POS + struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p)); + HDWP hdwp = begin_defer_window_pos (f); + HDWP new_hdwp; +#endif /* move the window before mapping it ... */ SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), NULL, @@ -2131,12 +2251,46 @@ mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y, SWP_NOZORDER | SWP_NOSIZE | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); /* ... now map it - we are not allowed to move it at the same time. */ - SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), - NULL, - 0, 0, 0, 0, - SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE - | SWP_SHOWWINDOW | SWP_NOCOPYBITS - | SWP_NOSENDCHANGING); + if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) + { +#ifdef DEFER_WINDOW_POS + new_hdwp = DeferWindowPos + (hdwp, + IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, 0, 0, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE + | SWP_SHOWWINDOW + /* | SWP_NOCOPYBITS */ + /* Setting this flag causes the call to + DeferWindowPos to fail with + "Invalid parameter". I don't understand + why we bother to try and set this + anyway. -- ben */ + /* | SWP_NOSENDCHANGING */ + | SWP_NOACTIVATE); + if (!new_hdwp) + mswindows_output_last_error ("mapping"); + else + hdwp = new_hdwp; + FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp; +#else + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, + 0, 0, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE + | SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOACTIVATE); + + /* Doing this once does not seem to be enough, for instance when + mapping the search dialog this gets called four times. If we + only set on the first time through then the subwindow never + gets focus as intended. However, doing this everytime doesn't + seem so bad, after all we only need to redo this after the + focus changes - and if that happens resetting the initial + focus doesn't seem so bad. */ + if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p)) + SetFocus (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)); +#endif + } } /* resize the subwindow instance */ @@ -2144,16 +2298,17 @@ static void mswindows_resize_subwindow (Lisp_Image_Instance* ii, int w, int h) { /* Set the size of the control .... */ - SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), - NULL, - 0, 0, w, h, - SWP_NOZORDER | SWP_NOMOVE - | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + if (!SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + NULL, + 0, 0, w, h, + SWP_NOZORDER | SWP_NOMOVE + | SWP_NOCOPYBITS | SWP_NOSENDCHANGING)) + mswindows_output_last_error ("resizing"); } /* Simply resize the window here. */ static void -mswindows_update_subwindow (Lisp_Image_Instance *p) +mswindows_redisplay_subwindow (Lisp_Image_Instance *p) { mswindows_resize_subwindow (p, IMAGE_INSTANCE_WIDTH (p), @@ -2163,27 +2318,31 @@ mswindows_update_subwindow (Lisp_Image_Instance *p) /* when you click on a widget you may activate another widget this needs to be checked and all appropriate widgets updated */ static void -mswindows_update_widget (Lisp_Image_Instance *p) +mswindows_redisplay_widget (Lisp_Image_Instance *p) { /* Possibly update the face font and colors. */ - if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)) + if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (p)) + && (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) + || XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed + || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))) { /* set the widget font from the widget face */ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), WM_SETFONT, (WPARAM) mswindows_widget_hfont - (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)), + (p, IMAGE_INSTANCE_FRAME (p)), MAKELPARAM (TRUE, 0)); } /* Possibly update the dimensions. */ if (IMAGE_INSTANCE_SIZE_CHANGED (p)) { - mswindows_resize_subwindow (p, + mswindows_resize_subwindow (p, IMAGE_INSTANCE_WIDTH (p), IMAGE_INSTANCE_HEIGHT (p)); } /* Possibly update the text in the widget. */ - if (IMAGE_INSTANCE_TEXT_CHANGED (p)) + if (IMAGE_INSTANCE_TEXT_CHANGED (p) + && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (p))) { Extbyte* lparam=0; TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p), @@ -2192,29 +2351,59 @@ mswindows_update_widget (Lisp_Image_Instance *p) SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), WM_SETTEXT, 0, (LPARAM)lparam); } + /* Set active state. */ + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) + { + Lisp_Object item = IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p); + LONG style = GetWindowLong + (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + GWL_STYLE); + + if (CONSP (item)) + item = XCAR (item); + + if (gui_item_active_p (item)) + SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + GWL_STYLE, style & ~WS_DISABLED); + else + SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + GWL_STYLE, style | WS_DISABLED); + } } -/* register widgets into our hastable so that we can cope with the +/* Account for some of the limitations with widget images. */ +static int +mswindows_widget_border_width (void) +{ + return DEFAULT_WIDGET_BORDER_WIDTH; +} + +/* register widgets into our hashtable so that we can cope with the callbacks. The hashtable is weak so deregistration is handled automatically */ static int -mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain) +mswindows_register_gui_item (Lisp_Object image_instance, + Lisp_Object gui, Lisp_Object domain) { - Lisp_Object frame = FW_FRAME (domain); + Lisp_Object frame = DOMAIN_FRAME (domain); struct frame* f = XFRAME (frame); - int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f), + int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f), gui, WIDGET_GLYPH_SLOT); - Fputhash (make_int (id), - XGUI_ITEM (gui)->callback, - FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f)); + Fputhash (make_int (id), image_instance, + FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f)); + Fputhash (make_int (id), XGUI_ITEM (gui)->callback, + FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f)); + Fputhash (make_int (id), XGUI_ITEM (gui)->callback_ex, + FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f)); return id; } static int mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain) { - return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_ITEM (instance), + return mswindows_register_gui_item (instance, + XIMAGE_INSTANCE_WIDGET_ITEM (instance), domain); } @@ -2225,7 +2414,7 @@ mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instant { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); - Lisp_Object frame = FW_FRAME (domain); + Lisp_Object frame = DOMAIN_FRAME (domain); HWND wnd; CHECK_MSWINDOWS_DEVICE (device); @@ -2347,7 +2536,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat /* this function can call lisp */ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style; - Lisp_Object frame = FW_FRAME (domain); + Lisp_Object frame = DOMAIN_FRAME (domain); Extbyte* nm=0; HWND wnd; int id = 0xffff; @@ -2361,7 +2550,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat style = pgui->style; - if (!NILP (pgui->callback)) + if (!NILP (pgui->callback) || !NILP (pgui->callback_ex)) { id = mswindows_register_widget_instance (image_instance, domain); } @@ -2385,7 +2574,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat IMAGE_INSTANCE_WIDGET_WIDTH (ii), IMAGE_INSTANCE_WIDGET_HEIGHT (ii), /* parent window */ - FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + DOMAIN_MSWINDOWS_HANDLE (domain), (HMENU)id, /* No menu */ NULL, /* must be null for this class */ NULL)) == NULL) @@ -2415,9 +2604,32 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd; SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance)); /* set the widget font from the widget face */ - SendMessage (wnd, WM_SETFONT, - (WPARAM) mswindows_widget_hfont (ii, domain), - MAKELPARAM (TRUE, 0)); + if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) + SendMessage (wnd, WM_SETFONT, + (WPARAM) mswindows_widget_hfont (ii, domain), + MAKELPARAM (TRUE, 0)); +} + +/* Instantiate a native layout widget. */ +static void +mswindows_native_layout_instantiate (Lisp_Object image_instance, + Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "STATIC", + /* Approximation to styles available with + an XEmacs layout. */ + (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii), + Qetched_in) || + EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii), + Qetched_out) || + GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) + ? SS_ETCHEDFRAME : SS_SUNKEN) | DS_CONTROL, + 0); } /* Instantiate a button widget. Unfortunately instantiated widgets are @@ -2434,9 +2646,10 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat /* This function can call lisp */ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); HWND wnd; - int flags = WS_TABSTOP;/* BS_NOTIFY #### is needed to get exotic feedback - only. Since we seem to want nothing beyond BN_CLICK, - the style is perhaps not necessary -- kkm */ + int flags = WS_TABSTOP | BS_NOTIFY; + /* BS_NOTIFY #### is needed to get exotic feedback only. Since we + seem to want nothing beyond BN_CLICK, the style is perhaps not + necessary -- kkm */ Lisp_Object style; Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); Lisp_Gui_Item* pgui = XGUI_ITEM (gui); @@ -2495,7 +2708,7 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat /* Update the state of a button. */ static void -mswindows_button_update (Lisp_Object image_instance) +mswindows_button_redisplay (Lisp_Object image_instance) { /* This function can GC if IN_REDISPLAY is false. */ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); @@ -2529,6 +2742,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in { HWND wnd; Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object val; mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, dest_mask, domain, PROGRESS_CLASS, WS_BORDER | PBS_SMOOTH, WS_EX_CLIENTEDGE); @@ -2540,7 +2754,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in (XCOLOR_INSTANCE (FACE_BACKGROUND (XIMAGE_INSTANCE_WIDGET_FACE (ii), - XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))))); + XIMAGE_INSTANCE_FRAME (ii)))))); #endif #ifdef PBS_SETBARCOLOR SendMessage (wnd, PBS_SETBARCOLOR, 0, @@ -2548,8 +2762,12 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in (XCOLOR_INSTANCE (FACE_FOREGROUND (XIMAGE_INSTANCE_WIDGET_FACE (ii), - XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))))); + XIMAGE_INSTANCE_FRAME (ii)))))); #endif + val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEMS (ii))->value; + CHECK_INT (val); + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + PBM_SETPOS, (WPARAM)XINT (val), 0); } /* instantiate a tree view widget */ @@ -2567,7 +2785,8 @@ static HTREEITEM add_tree_item (Lisp_Object image_instance, if (GUI_ITEMP (item)) { - tvitem.item.lParam = mswindows_register_gui_item (item, domain); + tvitem.item.lParam = mswindows_register_gui_item (image_instance, + item, domain); tvitem.item.mask |= TVIF_PARAM; TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name, C_STRING_ALLOCA, tvitem.item.pszText, @@ -2638,18 +2857,54 @@ mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instant } } +/* Set the properties of a tree view. */ +static void +mswindows_tree_view_redisplay (Lisp_Object image_instance) +{ + /* This function can GC if IN_REDISPLAY is false. */ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) + { + HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); + Lisp_Object rest; + HTREEITEM parent; + /* Delete previous items. */ + SendMessage (wnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); + /* define a root */ + parent = add_tree_item (image_instance, wnd, NULL, + XCAR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)), + TRUE, IMAGE_INSTANCE_DOMAIN (ii)); + + /* recursively add items to the tree view */ + /* add items to the tab */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) + { + if (LISTP (XCAR (rest))) + add_tree_item_list (image_instance, wnd, parent, XCAR (rest), + IMAGE_INSTANCE_DOMAIN (ii)); + else + add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, + IMAGE_INSTANCE_DOMAIN (ii)); + } + } +} + /* instantiate a tab control */ -static TC_ITEM* add_tab_item (Lisp_Object image_instance, - HWND wnd, Lisp_Object item, - Lisp_Object domain, int i) +static int +add_tab_item (Lisp_Object image_instance, + HWND wnd, Lisp_Object item, + Lisp_Object domain, int i) { - TC_ITEM tvitem, *ret; + TC_ITEM tvitem; + int ret = 0; tvitem.mask = TCIF_TEXT; if (GUI_ITEMP (item)) { - tvitem.lParam = mswindows_register_gui_item (item, domain); + tvitem.lParam = mswindows_register_gui_item (image_instance, + item, domain); tvitem.mask |= TCIF_PARAM; TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name, C_STRING_ALLOCA, tvitem.pszText, @@ -2665,8 +2920,8 @@ static TC_ITEM* add_tab_item (Lisp_Object image_instance, tvitem.cchTextMax = strlen (tvitem.pszText); - if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM, - i, (LPARAM)&tvitem)) < 0) + if ((ret = SendMessage (wnd, TCM_INSERTITEM, + i, (LPARAM)&tvitem)) < 0) signal_simple_error ("error adding tab entry", item); return ret; @@ -2702,7 +2957,8 @@ mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object insta /* add items to the tab */ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) { - add_tab_item (image_instance, wnd, XCAR (rest), domain, i); + int idx = add_tab_item (image_instance, wnd, XCAR (rest), domain, i); + assert (idx == i); if (gui_item_selected_p (XCAR (rest))) selected = i; i++; @@ -2710,37 +2966,78 @@ mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object insta SendMessage (wnd, TCM_SETCURSEL, selected, 0); } -/* set the properties of a tab control */ +/* Set the properties of a tab control. */ static void -mswindows_tab_control_update (Lisp_Object image_instance) +mswindows_tab_control_redisplay (Lisp_Object image_instance) { /* This function can GC if IN_REDISPLAY is false. */ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) +#ifdef DEBUG_WIDGET_OUTPUT + stderr_out ("tab control %p redisplayed\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); +#endif + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) + || + IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii)) { HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); - int i = 0, selected = 0; + int i = 0, selected_idx = 0; Lisp_Object rest; - /* delete the pre-existing items */ - SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0); + assert (!NILP (IMAGE_INSTANCE_WIDGET_ITEMS (ii))); - /* Pick up the items we recorded earlier. We do this here so - that the callbacks get set up with the new items. */ - IMAGE_INSTANCE_WIDGET_ITEMS (ii) = - IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii); - IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; - /* add items to the tab */ - LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) + /* If only the order has changed then simply select the first + one. This stops horrendous rebuilding of the tabs each time + you click on one. */ + if (tab_control_order_only_changed (image_instance)) { - add_tab_item (image_instance, wnd, XCAR (rest), - IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), i); - if (gui_item_selected_p (XCAR (rest))) - selected = i; - i++; + Lisp_Object selected = + gui_item_list_find_selected + (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ? + XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) : + XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))); + + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) + { + if (gui_item_equal_sans_selected (XCAR (rest), selected, 0)) + { + Lisp_Object old_selected = gui_item_list_find_selected + (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))); + + /* Pick up the new selected item. */ + XGUI_ITEM (old_selected)->selected = + XGUI_ITEM (XCAR (rest))->selected; + XGUI_ITEM (XCAR (rest))->selected = + XGUI_ITEM (selected)->selected; + /* We're not actually changing the items. */ + IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; + IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; + + SendMessage (wnd, TCM_SETCURSEL, i, 0); +#ifdef DEBUG_WIDGET_OUTPUT + stderr_out ("tab control %p selected item %d\n", + IMAGE_INSTANCE_SUBWINDOW_ID (ii), i); +#endif + break; + } + i++; + } + } + else + { + /* delete the pre-existing items */ + SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0); + + /* add items to the tab */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) + { + add_tab_item (image_instance, wnd, XCAR (rest), + IMAGE_INSTANCE_FRAME (ii), i); + if (gui_item_selected_p (XCAR (rest))) + selected_idx = i; + i++; + } + SendMessage (wnd, TCM_SETCURSEL, selected_idx, 0); } - SendMessage (wnd, TCM_SETCURSEL, selected, 0); } } @@ -2775,8 +3072,7 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); HWND wnd; Lisp_Object rest; - Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), - Q_items, Qnil); + Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); int len, height; /* Maybe ought to generalise this more but it may be very windows @@ -2790,9 +3086,9 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant /* We now have everything right apart from the height. */ default_face_font_info (domain, 0, 0, &height, 0, 0); - GET_LIST_LENGTH (data, len); + GET_LIST_LENGTH (items, len); - height = (height + WIDGET_BORDER_HEIGHT * 2 ) * len; + height = (height + DEFAULT_WIDGET_BORDER_WIDTH * 2 ) * len; IMAGE_INSTANCE_HEIGHT (ii) = height; /* Now create the widget. */ @@ -2806,12 +3102,14 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant image_instance_layout (image_instance, IMAGE_UNSPECIFIED_GEOMETRY, IMAGE_UNSPECIFIED_GEOMETRY, + IMAGE_UNCHANGED_GEOMETRY, + IMAGE_UNCHANGED_GEOMETRY, domain); wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); /* add items to the combo box */ SendMessage (wnd, CB_RESETCONTENT, 0, 0); - LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil)) + LIST_LOOP (rest, items) { Extbyte* lparam; TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (rest), @@ -2875,17 +3173,24 @@ mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop) return Qunbound; } -/* set the properties of a progres guage */ +/* set the properties of a progress gauge */ static void -mswindows_progress_gauge_update (Lisp_Object image_instance) +mswindows_progress_gauge_redisplay (Lisp_Object image_instance) { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - - if (IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii)) + + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) { - /* #### I'm not convinced we should store this in the plist. */ - Lisp_Object val = Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), - Q_percent, Qnil); + Lisp_Object val; +#ifdef ERROR_CHECK_GLYPHS + assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))); +#endif + val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value; +#ifdef DEBUG_WIDGET_OUTPUT + stderr_out ("progress gauge displayed value on %p updated to %ld\n", + WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), + XINT(val)); +#endif CHECK_INT (val); SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), PBM_SETPOS, (WPARAM)XINT (val), 0); @@ -2934,13 +3239,14 @@ console_type_create_glyphs_mswindows (void) CONSOLE_HAS_METHOD (mswindows, finalize_image_instance); CONSOLE_HAS_METHOD (mswindows, unmap_subwindow); CONSOLE_HAS_METHOD (mswindows, map_subwindow); - CONSOLE_HAS_METHOD (mswindows, update_subwindow); + CONSOLE_HAS_METHOD (mswindows, redisplay_subwindow); CONSOLE_HAS_METHOD (mswindows, resize_subwindow); - CONSOLE_HAS_METHOD (mswindows, update_widget); + CONSOLE_HAS_METHOD (mswindows, redisplay_widget); CONSOLE_HAS_METHOD (mswindows, image_instance_equal); CONSOLE_HAS_METHOD (mswindows, image_instance_hash); CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage); CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file); + CONSOLE_HAS_METHOD (mswindows, widget_border_width); /* image methods - printer */ CONSOLE_INHERITS_METHOD (msprinter, mswindows, print_image_instance); @@ -2956,7 +3262,6 @@ image_instantiator_format_create_glyphs_mswindows (void) { IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, nothing); IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, string); - IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, layout); IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, formatted_string); IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, inherit); /* image-instantiator types */ @@ -2989,48 +3294,45 @@ image_instantiator_format_create_glyphs_mswindows (void) IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, gif); #endif #ifdef HAVE_WIDGETS + INITIALIZE_DEVICE_IIFORMAT (mswindows, widget); + IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property); + /* layout widget */ + IIFORMAT_VALID_CONSOLE (mswindows, layout); + INITIALIZE_DEVICE_IIFORMAT (mswindows, native_layout); + IIFORMAT_HAS_DEVMETHOD (mswindows, native_layout, instantiate); /* button widget */ INITIALIZE_DEVICE_IIFORMAT (mswindows, button); IIFORMAT_HAS_DEVMETHOD (mswindows, button, property); IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate); - IIFORMAT_HAS_DEVMETHOD (mswindows, button, update); - + IIFORMAT_HAS_DEVMETHOD (mswindows, button, redisplay); + /* edit-field widget */ INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field); IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate); - + /* subwindow */ INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow); IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate); - - INITIALIZE_DEVICE_IIFORMAT (mswindows, widget); - IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property); - /* label */ INITIALIZE_DEVICE_IIFORMAT (mswindows, label); IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate); - /* combo box */ INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box); IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property); IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate); - /* scrollbar */ INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar); IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate); - /* progress gauge */ INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge); - IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, update); + IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, redisplay); IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate); - /* tree view widget */ INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view); - /* IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/ IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate); - + IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, redisplay); /* tab control widget */ INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control); IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate); - IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, update); + IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, redisplay); #endif /* windows bitmap format */ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");