Mercurial > hg > xemacs-beta
diff src/toolbar-msw.c @ 278:90d73dddcdc4 r21-0b37
Import from CVS: tag r21-0b37
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:31:29 +0200 |
parents | 6330739388db |
children | 7df0dd720c89 |
line wrap: on
line diff
--- a/src/toolbar-msw.c Mon Aug 13 10:30:38 2007 +0200 +++ b/src/toolbar-msw.c Mon Aug 13 10:31:29 2007 +0200 @@ -31,6 +31,7 @@ #include "toolbar.h" #include "window.h" #include "gui.h" +#include "elhash.h" #include "console-msw.h" #include "glyphs-msw.h" #include "objects-msw.h" @@ -39,9 +40,13 @@ #define TOOLBAR_ITEM_ID_MIN 0x4000 #define TOOLBAR_ITEM_ID_MAX 0x7FFF #define TOOLBAR_ITEM_ID_BITS(x) (((x) & 0x3FFF) | 0x4000) +#define TOOLBAR_ID_BIAS 16 +#define TOOLBAR_HANDLE(f,p) \ +GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + p) #ifndef TB_SETIMAGELIST #define TB_SETIMAGELIST (WM_USER + 48) #define TB_GETIMAGELIST (WM_USER + 49) +#define TB_SETPADDING (WM_USER + 87) #endif #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ @@ -66,7 +71,8 @@ } while (0) static int -allocate_toolbar_item_id (struct frame* f, struct toolbar_button* button) +allocate_toolbar_item_id (struct frame* f, struct toolbar_button* button, + enum toolbar_pos pos) { /* hmm what do we generate an id based on */ int id = TOOLBAR_ITEM_ID_BITS (internal_hash (button->callback, 0)); @@ -83,24 +89,37 @@ int thickness_change) { HIMAGELIST ilist=NULL; - if (FRAME_MSWINDOWS_TOOLBAR (f)) + int i; + HWND toolbarwnd = TOOLBAR_HANDLE(f, pos); + if (toolbarwnd) { - /* get the image list and delete it */ - SendMessage (FRAME_MSWINDOWS_TOOLBAR (f), - TB_GETIMAGELIST, 0, - (LONG) &ilist); + TBBUTTON info; - /* destroy the toolbar window */ - DestroyWindow (FRAME_MSWINDOWS_TOOLBAR (f)); - FRAME_MSWINDOWS_TOOLBAR (f) = 0; - + /* delete the buttons and remove the command from the hashtable*/ + i = SendMessage (toolbarwnd, TB_BUTTONCOUNT, 0, 0); + for (i--; i >= 0; i--) + { + SendMessage (toolbarwnd, TB_GETBUTTON, (WPARAM)i, + (LPARAM)&info); + Fremhash(make_int(info.idCommand), + FRAME_MSWINDOWS_TOOLBAR_HASHTABLE(f)); + SendMessage (toolbarwnd, TB_DELETEBUTTON, (WPARAM)i, 0); + } + /* finally get rid of the image list assuming it clears up its bitmaps */ + SendMessage (toolbarwnd, TB_GETIMAGELIST, 0, (LONG) &ilist); if (ilist) { ImageList_Destroy(ilist); } + SendMessage (toolbarwnd, TB_SETIMAGELIST, 0, (LPARAM)NULL); + + ShowWindow(toolbarwnd, SW_HIDE); } + + FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)=0; + SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0); } static void @@ -111,24 +130,34 @@ int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos); Lisp_Object button, window, glyph, instance; int nbuttons=0; + int shadow_thickness = 2; /* get this from somewhere else? */ + int window_frame_width = 3; + unsigned int checksum=0; struct window *w; TBBUTTON* button_tbl, *tbbutton; HIMAGELIST ilist=NULL; + HWND toolbarwnd=NULL; get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 0); + + if (x==1) + x=0; + window = FRAME_LAST_NONMINIBUF_WINDOW (f); w = XWINDOW (window); + toolbarwnd = TOOLBAR_HANDLE(f,pos); + /* set button sizes based on bar size */ if (vert) { - width = height = bar_width - border_width * 2; - bmwidth = bmheight = width -2; + width = height = bar_width; + bmwidth = bmheight = width - (border_width + shadow_thickness) * 2; } else { - height = width = bar_height - border_width * 2; - bmwidth = bmheight = width -2; + height = width = bar_height - window_frame_width * 2; + bmwidth = bmheight = width - (border_width + shadow_thickness) * 2; } button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons; @@ -140,132 +169,249 @@ while (!NILP (button)) { struct toolbar_button *tb = XTOOLBAR_BUTTON (button); + checksum = HASH3 (checksum, + internal_hash (get_toolbar_button_glyph(w, tb), 0), + internal_hash (tb->callback, 0)); button = tb->next; nbuttons++; } - /* build up the data required by win32 fns. */ - button_tbl = xnew_array_and_zero (TBBUTTON, nbuttons); - button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons; - tbbutton = button_tbl; - - while (!NILP (button)) + /* only rebuild if something has changed */ + if (!toolbarwnd || FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)!=checksum) { - struct toolbar_button *tb = XTOOLBAR_BUTTON (button); + /* remove the old one */ + mswindows_clear_toolbar (f, pos, 0); - tbbutton->idCommand = allocate_toolbar_item_id (f, tb); - tbbutton->fsState=tb->enabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE; - tbbutton->fsStyle=tb->blank ? TBSTYLE_SEP : TBSTYLE_BUTTON; - tbbutton->dwData=0; - tbbutton->iString=0; - - /* mess with the button image */ - glyph = get_toolbar_button_glyph (w, tb); + FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)=checksum; - if (GLYPHP (glyph)) - instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); - else - instance = Qnil; - - if (IMAGE_INSTANCEP (instance)) - { - struct Lisp_Image_Instance* p = XIMAGE_INSTANCE (instance); + /* build up the data required by win32 fns. */ + button_tbl = xnew_array_and_zero (TBBUTTON, nbuttons); + button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons; + tbbutton = button_tbl; - if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p)) + while (!NILP (button)) + { + struct toolbar_button *tb = XTOOLBAR_BUTTON (button); + + tbbutton->idCommand = allocate_toolbar_item_id (f, tb, pos); + tbbutton->fsState=tb->enabled ? TBSTATE_ENABLED + : TBSTATE_INDETERMINATE; + tbbutton->fsStyle=tb->blank ? TBSTYLE_SEP : TBSTYLE_BUTTON; + tbbutton->dwData=0; + tbbutton->iString=0; + + /* note that I am not doing the button size here. This is + because it is slightly out of my control and the main + place they are used is in redisplay for getting events + over toolbar buttons. Since the right way to do help echo + is with tooltips I'm not going to bother with the extra + work involved. */ + + /* mess with the button image */ + glyph = get_toolbar_button_glyph (w, tb); + + if (GLYPHP (glyph)) + instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + else + instance = Qnil; + + if (IMAGE_INSTANCEP (instance)) { - /* we are going to honour the toolbar settings and - resize the bitmaps accordingly */ + struct Lisp_Image_Instance* p = XIMAGE_INSTANCE (instance); - if ((IMAGE_INSTANCE_PIXMAP_WIDTH (p) != bmwidth - || - IMAGE_INSTANCE_PIXMAP_HEIGHT (p) != bmheight) - && - !mswindows_resize_dibitmap_instance (p, f, - bmwidth, bmheight)) + if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p)) { - xfree (button_tbl); - if (ilist) ImageList_Destroy (ilist); - signal_simple_error ("couldn't resize pixmap", - instance); - } + /* we are going to honour the toolbar settings and + resize the bitmaps accordingly */ + + if (IMAGE_INSTANCE_PIXMAP_WIDTH (p) > bmwidth + || + IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > bmheight) + { + if (!mswindows_resize_dibitmap_instance + (p, f, bmwidth, bmheight)) + { + xfree (button_tbl); + if (ilist) ImageList_Destroy (ilist); + signal_simple_error ("couldn't resize pixmap", + instance); + } + } + else + { + bmwidth = IMAGE_INSTANCE_PIXMAP_WIDTH (p); + bmheight = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); + } - /* need to build an image list for the bitmaps */ - if (!ilist) - { - if (!(ilist = ImageList_Create - ( IMAGE_INSTANCE_PIXMAP_WIDTH (p), - IMAGE_INSTANCE_PIXMAP_HEIGHT (p), - ILC_COLOR24, - nbuttons, - nbuttons * 2 ))) + /* need to build an image list for the bitmaps */ + if (!ilist) + { + if (!(ilist = ImageList_Create + ( IMAGE_INSTANCE_PIXMAP_WIDTH (p), + IMAGE_INSTANCE_PIXMAP_HEIGHT (p), + ILC_COLOR24, + nbuttons, + nbuttons * 2 ))) + { + xfree (button_tbl); + signal_simple_error ("couldn't create image list", + instance); + } + } + + /* add a bitmap to the list */ + if ((tbbutton->iBitmap = + ImageList_Add (ilist, + IMAGE_INSTANCE_MSWINDOWS_BITMAP (p), + IMAGE_INSTANCE_MSWINDOWS_MASK (p))) < 0) { xfree (button_tbl); - signal_simple_error ("couldn't create image list", + if (ilist) ImageList_Destroy (ilist); + signal_simple_error ("image list creation failed", instance); } } - - /* add a bitmap to the list */ - if ((tbbutton->iBitmap = - ImageList_Add (ilist, - IMAGE_INSTANCE_MSWINDOWS_BITMAP (p), - IMAGE_INSTANCE_MSWINDOWS_MASK (p))) < 0) - { - xfree (button_tbl); - if (ilist) ImageList_Destroy (ilist); - signal_simple_error ("image list creation failed", - instance); - } } + + Fputhash (make_int (tbbutton->idCommand), + button, FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f)); + + tbbutton++; + button = tb->next; + } + + button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons; + + /* create the toolbar window? */ + if (!toolbarwnd + && + (toolbarwnd = + CreateWindowEx ( WS_EX_WINDOWEDGE, + TOOLBARCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE | WS_DLGFRAME | TBSTYLE_TOOLTIPS + | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER, + x, y, bar_width, bar_height, + FRAME_MSWINDOWS_HANDLE (f), + (HMENU)(TOOLBAR_ID_BIAS + pos), + NULL, + NULL))==NULL) + { + xfree (button_tbl); + ImageList_Destroy (ilist); + error ("couldn't create toolbar"); + } +#if 0 + SendMessage (toolbarwnd, TB_SETPADDING, + 0, MAKELPARAM(border_width, border_width)); +#endif + /* finally populate with images */ + if (SendMessage (toolbarwnd, TB_BUTTONSTRUCTSIZE, + (WPARAM)sizeof(TBBUTTON), (LPARAM)0) == -1) + { + mswindows_clear_toolbar (f, pos, 0); + error ("couldn't set button structure size"); + } + + /* set the size of buttons */ + SendMessage (toolbarwnd, TB_SETBUTTONSIZE, 0, + (LPARAM)MAKELONG (width, height)); + + /* set the size of bitmaps */ + SendMessage (toolbarwnd, TB_SETBITMAPSIZE, 0, + (LPARAM)MAKELONG (bmwidth, bmheight)); + + /* finally populate with images */ + if (!SendMessage (toolbarwnd, TB_ADDBUTTONS, + (WPARAM)nbuttons, (LPARAM)button_tbl)) + { + mswindows_clear_toolbar (f, pos, 0); + error ("couldn't add button list to toolbar"); + } + + /* vertical toolbars need more rows */ + if (vert) + { + SendMessage (toolbarwnd, TB_SETROWS, + MAKEWPARAM(nbuttons, FALSE), 0); + } + + else + { + SendMessage (toolbarwnd, TB_SETROWS, MAKEWPARAM(1, FALSE), 0); } - Fputhash (make_int (tbbutton->idCommand), - tb->callback, FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f)); - - tbbutton++; - button = tb->next; - } + /* finally populate with images */ + if (SendMessage (toolbarwnd, TB_SETIMAGELIST, 0, + (LPARAM)ilist) == -1) + { + mswindows_clear_toolbar (f, pos, 0); + error ("couldn't add image list to toolbar"); + } - button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons; + /* now display the window */ + ShowWindow (toolbarwnd, SW_SHOW); - /* now create the toolbar ... */ - if ((FRAME_MSWINDOWS_TOOLBAR (f) = - CreateToolbarEx (FRAME_MSWINDOWS_HANDLE (f), - TBSTYLE_ALTDRAG | WS_CHILD, - NULL, - nbuttons, - 0, - 0, - button_tbl, - nbuttons, - width, height, - bmwidth, bmheight, - sizeof(TBBUTTON) )) == NULL) + if (button_tbl) xfree (button_tbl); + + SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1); + } +} + +static void +mswindows_move_toolbar (struct frame *f, enum toolbar_pos pos) +{ + int bar_x, bar_y, bar_width, bar_height, vert; + HWND toolbarwnd = TOOLBAR_HANDLE(f,pos); + + if (toolbarwnd) { - xfree (button_tbl); - ImageList_Destroy (ilist); - error ("couldn't create toolbar"); - } + get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height, + &vert, 1); - /* finally populate with images */ - if (SendMessage (FRAME_MSWINDOWS_TOOLBAR (f), TB_SETIMAGELIST, NULL, - (LPARAM)ilist) == -1) - { - mswindows_clear_toolbar (f, pos, 0); - error ("couldn't add image list to toolbar"); + /* #### This terrible mangling with coordinates perhaps + arises from different treatment of toolbar positions + by Windows and by XEmacs. */ + switch (pos) + { + case TOP_TOOLBAR: + bar_x -= 2; bar_y--; + bar_width += 2; bar_height++; + break; + case LEFT_TOOLBAR: + bar_x -= 2; bar_y--; + bar_width++; bar_height++; + break; + case BOTTOM_TOOLBAR: + bar_x--; + bar_width++; + break; + case RIGHT_TOOLBAR: + bar_y--; + break; + } + SetWindowPos (toolbarwnd, NULL, bar_x, bar_y, + bar_width + 1, bar_height + 1, SWP_NOZORDER); } +} - /* now move the window */ - SetWindowPos (FRAME_MSWINDOWS_TOOLBAR (f), HWND_TOP, x, y, - bar_width, bar_height, - SWP_SHOWWINDOW); -#if 0 - ShowWindow (FRAME_MSWINDOWS_TOOLBAR (f), SW_SHOWNORMAL); -#endif +static void +mswindows_redraw_exposed_toolbars (struct frame *f, int x, int y, int width, + int height) +{ + assert (FRAME_MSWINDOWS_P (f)); + + if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) + mswindows_move_toolbar (f, TOP_TOOLBAR); - if (button_tbl) xfree (button_tbl); + if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) + mswindows_move_toolbar (f, BOTTOM_TOOLBAR); - SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1); + if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) + mswindows_move_toolbar (f, LEFT_TOOLBAR); + + if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) + mswindows_move_toolbar (f, RIGHT_TOOLBAR); } static void @@ -303,7 +449,51 @@ static void mswindows_free_frame_toolbars (struct frame *f) { - mswindows_clear_toolbar(f, 0, 0); + HWND twnd=NULL; +#define DELETE_TOOLBAR(pos) \ + mswindows_clear_toolbar(f, 0, pos); \ + if ((twnd=GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + pos))) \ + DestroyWindow(twnd) + + DELETE_TOOLBAR(TOP_TOOLBAR); + DELETE_TOOLBAR(BOTTOM_TOOLBAR); + DELETE_TOOLBAR(LEFT_TOOLBAR); + DELETE_TOOLBAR(RIGHT_TOOLBAR); +#undef DELETE_TOOLBAR +} + +/* map toolbar hwnd to pos*/ +int mswindows_find_toolbar_pos(struct frame* f, HWND ctrl) +{ +#if 1 + int id = GetDlgCtrlID(ctrl); + return id ? id - TOOLBAR_ID_BIAS : -1; +#else + if (GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS) == ctrl) + return 0; + else if (GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS +1) == ctrl) + return 1; + else if (GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS +2) == ctrl) + return 2; + else if (GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS +3) == ctrl) + return 3; + else + assert(0); +#endif +} + +Lisp_Object +mswindows_get_toolbar_button_text ( struct frame* f, int command_id ) +{ + Lisp_Object button = Fgethash (make_int (command_id), + FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qnil); + + if (!NILP (button)) + { + struct toolbar_button *tb = XTOOLBAR_BUTTON (button); + return tb->help_string; + } + return Qnil; } /* @@ -313,19 +503,23 @@ * command if we return nil */ Lisp_Object -mswindows_handle_toolbar_wm_command (struct frame* f, WORD id) +mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id) { /* Try to map the command id through the proper hash table */ - Lisp_Object command, funcsym, frame; + Lisp_Object button, command, funcsym, frame; struct gcpro gcpro1; + + button = Fgethash (make_int (id), + FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qnil); - command = Fgethash (make_int (id), - FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qunbound); - if (UNBOUNDP (command)) - { - return Qnil; - } + if (NILP (button)) + return Qnil; + command = XTOOLBAR_BUTTON(button)->callback; + + if (UNBOUNDP(command)) + return Qnil; + /* Need to gcpro because the hashtable may get destroyed by menu_cleanup(), and will not gcpro the command any more */ @@ -363,5 +557,6 @@ CONSOLE_HAS_METHOD (mswindows, output_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, initialize_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, free_frame_toolbars); + CONSOLE_HAS_METHOD (mswindows, redraw_exposed_toolbars); }