From 899184656a08484f2a0afcdf87796a042f1dba63 Mon Sep 17 00:00:00 2001 From: Fabien Costantini Date: Thu, 4 Dec 2008 17:33:30 +0000 Subject: STR#2086 related Fixes : This one was really tough to track, understand: In fact, the problem was comming from the misplacement of the menu window, which itself came from invalid measurement, which itself came from invalid fl_witdh() measurement, but only when fl_gc is not valid because fl_width() relies on Win32 on the call of GetTextExtentPoint32W which can't succeed if the HDC(here fl_gc) is not valid ! Now the fix: A best-effort algorithm has been furthered to supply a valid fltk hdc if we can have one or a screen hdc if no fltk window is found by fl::first_window(). Note that when fl_gc is NULL inside fl_width() call, it can happen that Fl_Window::current() is not null but invalid (already deleted). Finally, in the case of the buggy menu window observed here, this fl_gc was set to NULL just after an Fl_Menu_Window deletion and re-creation in Fl_Menu_Item::pulldown(). Also added a comment to describe the new fl_width() behavior. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6540 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/Fl_Menu.cxx | 11 ++++++----- src/fl_draw.cxx | 2 +- src/fl_font.cxx | 2 ++ src/fl_font_win32.cxx | 15 ++++++++++++++- 4 files changed, 23 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx index 68e60fb02..bf6e4b4bf 100644 --- a/src/Fl_Menu.cxx +++ b/src/Fl_Menu.cxx @@ -80,7 +80,7 @@ const Fl_Menu_Item* Fl_Menu_Item::next(int n) const { } // appearance of current menus are pulled from this parent widget: -static const Fl_Menu_* button; +static const Fl_Menu_* button=0; //////////////////////////////////////////////////////////////// @@ -320,7 +320,8 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, if (t) Wtitle = t->measure(&Htitle, button) + 12; int W = 0; if (m) for (; m->text; m = m->next()) { - int hh; int w1 = m->measure(&hh, button); + int hh; + int w1 = m->measure(&hh, button); if (hh+LEADING>itemheight) itemheight = hh+LEADING; if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14; if (w1 > W) W = w1; @@ -541,7 +542,7 @@ struct menustate { menuwindow* fakemenu; // kludge for buttons in menubar int is_inside(int mx, int my); }; -static menustate* p; +static menustate* p=0; // return 1 if the coordinates are inside any of the menuwindows int menustate::is_inside(int mx, int my) { @@ -826,7 +827,7 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown( if (pp.current_item == oldi) continue;} // only do rest if item changes: - delete pp.fakemenu; pp.fakemenu = 0; // turn off "menubar button" + if(pp.fakemenu) {delete pp.fakemenu; pp.fakemenu = 0;} // turn off "menubar button" if (!pp.current_item) { // pointing at nothing // turn off selection in deepest menu, but don't erase other menus: @@ -834,7 +835,7 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown( continue; } - delete pp.fakemenu; pp.fakemenu = 0; + if(pp.fakemenu) {delete pp.fakemenu; pp.fakemenu = 0;} initial_item = 0; // stop the startup code pp.p[pp.menu_number]->autoscroll(pp.item_number); diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx index d4b42cec7..142d72d5e 100644 --- a/src/fl_draw.cxx +++ b/src/fl_draw.cxx @@ -368,7 +368,7 @@ void fl_measure(const char* str, int& w, int& h, int draw_symbols) { char buf[MAXBUF]; int buflen; int lines; - double width; + double width=0; int W = 0; char symbol[2][255], *symptr; int symwidth[2], symtotal; diff --git a/src/fl_font.cxx b/src/fl_font.cxx index 20bdc198b..6f9a1e0f6 100644 --- a/src/fl_font.cxx +++ b/src/fl_font.cxx @@ -26,7 +26,9 @@ // #ifdef WIN32 +#ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN +#endif /* We require Windows 2000 features such as GetGlyphIndices */ # if !defined(WINVER) || (WINVER < 0x0500) # define WINVER 0x0500 diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx index 42ca214d3..0155dfcea 100644 --- a/src/fl_font_win32.cxx +++ b/src/fl_font_win32.cxx @@ -182,11 +182,24 @@ double fl_width(unsigned int c) { fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400); SIZE s; unsigned short i = 0, ii = r * 0x400; + // The following code is a best effort algorithm to further a valid fl_gc + // if no fl_gc is available at the time we call fl_width() + // We first choose a gc from the first fltk window, + // if it is null then the gc from the current screen (GetDC(NULL)). + // This should solve STR #2086 + HDC gc = fl_gc; + HWND hWnd = 0; + if (!gc) { + gc = GetDC(hWnd); + } + if (!gc) + Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!"); for (; i < 0x400; i++) { - GetTextExtentPoint32W(fl_gc, (WCHAR*)&ii, 1, &s); + GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s); fl_fontsize->width[r][i] = s.cx; ii++; } + if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc); } return (double) fl_fontsize->width[r][c & 0x03FF]; } -- cgit v1.2.3