diff --git a/ChangeLog b/ChangeLog index 59d5518746c..e7dfebddcb1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,118 @@ +---------------------------------------------------------------------- +Tue Aug 9 23:58:29 MET DST 1994 + + * [misc/file.c] + OpenFile(): Completly rewritten. + + * [miscemu/int21.c] + CreateFile(): Fixed wrong mode in call to open. + OpenExistingFile(): Implemented file sharing. + FindNext(): Fixed. + CreateNewFile(): Fixed wrong mode in call to open. + fLock(): Added to handle record locking. + GetFileAttribute(): Added. + As a result, AH = 0x5c, 0x09, and 0x0b were changed. + + * [miscemu/int2f.c] + AH = 0x10: SHARE installation check + + * [loader/resource.c] + AccessResource(): Fixed. A new file descriptor will be returned by + every call to AccessResource(). + + * [windows/utility.c] + wvsprintf(): Fixed. + + * [controls/menu.c] + FindMenuItem(): Fixed (handling for nPos == -1 added). + + * [windows/win.c] + CreateWindowEx(): Added call to WINPOS_GetMinMaxInfo. + + * [Configure] + Added two options for a processor emulator that might be + plugged in later.. + + * [loader/task.c] [include/toolhelp.h] [if1632/toolhelp.spec] + CreateNewTask() stores real modulename instead of 'TASKxxxx'. + Added TaskFirst(), TaskNext(), TaskFindHandle(). + + * [memory/global.c] + Added stub for MemManInfo(). + + * [objects/text.c] + Added stub for GetTabbedTextExt(). + + * [miscemu/*] + Changed all references to registers. Please don't access + the context structure. + fix for GetSystemTime() by added. + + * [misc/lstr.c] + Fixed bug in AnsiUpper() & AnsiLower(). + + * [misc/winsocket.c] + bugfix in getsockopt()/setsockopt(): winsock uses different values + than unix. + + * [objects/dib.c] + Added DIB_SetImageBits_RLE[48] to support compressed bitmaps. + +Mon Aug 8 21:12:33 1994 David Metcalfe + + * [controls/edit.c] + Added support for WM_COPY, WM_CUT and WM_PASTE messages. + + * [windows/dialog.c] [windows/defdlg.c] [include/dialog.h] + Modified dialog code to create new heap for edit controls + unless DS_LOCALEDIT style is set. + +Thu Aug 4 18:50:56 1994 Alexandre Julliard (julliard@lamisun.epfl.ch) + + * [controls/button.c] [controls/edit.c] [controls/static.c] + Removed unneeded GlobalUnlock() calls. + + * [controls/menu.c] [include/menu.h] + Lots of changes, fixed a lot of old bugs and introduced a lot of + new ones :-) + - Changed message loop to use MSG_GetInternalMessage(). + - Fixed a bug that caused the main window to lose activation when + displaying a menu. + - Correctly send initialisation messages (WM_INITMENUPOPUP). + - Implemented EndMenu() and LookupMenuHandle(). + - Changed internal structures to be as compatible as possible with + MS-Windows. + - Allocated everything on the USER heap instead of the global heap. + - Prefixed all internal function names with MENU_ and declared + them static. + - Moved "About Wine..." handling to NC_HandleSysCommand(). + - Multi-line menus should now work correctly. + + * [loader/resource.c] [objects/bitmap.c] + Added the possibility to create OEM bitmaps directly as X bitmaps. + + * [objects/dcvalues.c] [windows/dc.c] + Fixed GetDCOrg() to return screen coordinates. + + * [windows/message.c] + Fixed double-click checks when the message is not removed from the + queue. + Fixed MSG_GetInternalMessage() to send WM_ENTERIDLE messages. + + * [windows/nonclient.c] + Bug fix in system menu hit-test calculation. + A few changes for new menu functions. + +Thu Aug 11 17:51:02 1994 Thomas Sandford + + * [controls/edit.c] + Bug fix in Edit_NCCreateMessage + es->textlen was being used before being set + + * [controls/menu.c] + Bug fix in MENU_DrawMenuItem + don't try to write text if NULL pointer passed + ---------------------------------------------------------------------- Thu Aug 4 07:18:02 1994 Michael Patra diff --git a/Configure b/Configure index 1cb4d5c4f07..c2fee7d59cc 100644 --- a/Configure +++ b/Configure @@ -11,8 +11,23 @@ then ALLDEFINES="$ALLDEFINES -DWINELIB" else WINELIB='' + echo -n 'Use processor emulator (*DOES*NOT*WORK*YET*) (Y/N) [N]? ' + read input + if [ "$input" = 'y' -o "$input" = 'Y' ] + then + PROCEMU='#define PROCEMU' + echo -n 'bochs directory [/usr/src/bochs]? ' + read input + if [ "$input" = '' ] + then + ALLDEFINES="$ALLDEFINES -DPROC_EMU_DIR=/usr/src/bochs" + else + ALLDEFINES="$ALLDEFINES -DPROC_EMU_DIR="$input + fi + fi fi +echo echo -n 'Short filenames (Y/N) [N]? ' read input if [ "$input" = 'y' -o "$input" = 'Y' ] @@ -47,17 +62,13 @@ else NEWBUILD='' fi +NEWLINUXLDT='' if [ -f /usr/include/linux/ldt.h ] then - if grep -q seg_not_present /usr/include/linux/ldt.h + if grep seg_not_present /usr/include/linux/ldt.h then - NEWLINUXLDT='#define NewLinuxLdt -DNEW_LDT_STRUCT' - ALLDEFINES="$ALLDEFINES -DNEW_LDT_STRUCT" - else - NEWLINUXLDT='' + NEWLINUXLDT='#define NEW_LDT_STRUCT' fi -else - NEWLINUXLDT='' fi echo '/* autoconf.h generated automatically. Run Configure. */' > autoconf.h @@ -66,6 +77,9 @@ echo $SHORTNAMES >> autoconf.h echo $NEWBUILD >> autoconf.h echo $WINE_INI_GLOBAL >> autoconf.h echo $NEWLINUXLDT >> autoconf.h +echo $ENDIAN >> autoconf.h +echo $PROCEMU >> autoconf.h +echo $PROCEMUDIR >> autoconf.h echo "#define AutoDefines $ALLDEFINES" >> autoconf.h xmkmf -a diff --git a/controls/button.c b/controls/button.c index 67de0ab3ee6..a5d39469446 100644 --- a/controls/button.c +++ b/controls/button.c @@ -254,7 +254,6 @@ LONG ButtonWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam) break; } - GlobalUnlock(hWnd); return lResult; } @@ -522,7 +521,6 @@ static LONG CB_Paint(HWND hWnd) SelectObject(hDC, hOldPen); USER_HEAP_FREE(hText); - GlobalUnlock(hWnd); EndPaint(hWnd, &ps); } @@ -604,7 +602,6 @@ static LONG CB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam) } NOTIFY_PARENT(hWnd, BN_CLICKED); } - GlobalUnlock(hWnd); InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); } @@ -644,7 +641,6 @@ static LONG CB_SetCheck(HWND hWnd, WORD wParam) InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); } - GlobalUnlock(hWnd); } static LONG CB_GetCheck(HWND hWnd) @@ -653,7 +649,6 @@ static LONG CB_GetCheck(HWND hWnd) WND *wndPtr = WIN_FindWndPtr(hWnd); wResult = (WORD)(*(wndPtr->wExtra)); - GlobalUnlock(hWnd); return (LONG)wResult; } @@ -723,7 +718,6 @@ static LONG RB_Paint(HWND hWnd) SelectObject(hDC, hOldPen ); USER_HEAP_FREE(hText); - GlobalUnlock(hWnd); EndPaint(hWnd, &ps); } @@ -777,7 +771,6 @@ static LONG RB_LButtonUp(HWND hWnd, WORD wParam, LONG lParam) (WORD)(*(wndPtr->wExtra)) = 1; NOTIFY_PARENT(hWnd, BN_CLICKED); } - GlobalUnlock(hWnd); InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); } @@ -817,7 +810,6 @@ static LONG RB_SetCheck(HWND hWnd, WORD wParam) InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); } - GlobalUnlock(hWnd); } static LONG RB_GetCheck(HWND hWnd) @@ -826,7 +818,6 @@ static LONG RB_GetCheck(HWND hWnd) WND *wndPtr = WIN_FindWndPtr(hWnd); wResult = (WORD)(*(wndPtr->wExtra)); - GlobalUnlock(hWnd); return (LONG)wResult; } diff --git a/controls/edit.c b/controls/edit.c index 7f00cb85589..bcbe8f28fc6 100644 --- a/controls/edit.c +++ b/controls/edit.c @@ -17,12 +17,6 @@ static char Copyright[] = "Copyright David W. Metcalfe, 1994"; #include "user.h" #include "scroll.h" -#define EDIT_HEAP_ALLOC(size) USER_HEAP_ALLOC(GMEM_MOVEABLE,size) -#define EDIT_HEAP_REALLOC(handle,size) USER_HEAP_REALLOC(handle,size,\ - GMEM_MOVEABLE) -#define EDIT_HEAP_ADDR(handle) USER_HEAP_ADDR(handle) -#define EDIT_HEAP_FREE(handle) USER_HEAP_FREE(handle) - /* #define DEBUG_EDIT /* */ #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \ @@ -37,7 +31,6 @@ static char Copyright[] = "Copyright David W. Metcalfe, 1994"; #define HSCROLLDIM (ClientWidth(wndPtr) / 3) /* "line" dimension for horizontal scroll */ - typedef struct { int wlines; /* number of lines of text */ @@ -172,6 +165,8 @@ void EDIT_HeapFree(HWND hwnd, unsigned int handle); unsigned int EDIT_HeapSize(HWND hwnd, unsigned int handle); void EDIT_SetHandleMsg(HWND hwnd, WORD wParam); LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam); +void EDIT_CopyToClipboard(HWND hwnd); +void EDIT_PasteMsg(HWND hwnd); void swap(int *a, int *b); @@ -326,10 +321,20 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam) EDIT_CharMsg(hwnd, wParam); break; + case WM_COPY: + EDIT_CopyToClipboard(hwnd); + EDIT_ClearSel(hwnd); + break; + case WM_CREATE: lResult = EDIT_CreateMsg(hwnd, lParam); break; + case WM_CUT: + EDIT_CopyToClipboard(hwnd); + EDIT_DeleteSel(hwnd); + break; + case WM_DESTROY: EDIT_HeapFree(hwnd, es->hTextPtrs); EDIT_HeapFree(hwnd, es->hCharWidths); @@ -403,6 +408,10 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam) EDIT_PaintMsg(hwnd); break; + case WM_PASTE: + EDIT_PasteMsg(hwnd); + break; + case WM_SETFOCUS: CreateCaret(hwnd, 0, 2, es->txtht); SetCaretPos(es->WndCol, es->WndRow * es->txtht); @@ -435,7 +444,6 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam) break; } - GlobalUnlock(hwnd); return lResult; } @@ -479,11 +487,11 @@ long EDIT_NCCreateMsg(HWND hwnd, LONG lParam) { if (strlen(createStruct->lpszName) < EditBufLen(wndPtr)) { + es->textlen = EditBufLen(wndPtr) + 1; es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2); text = EDIT_HeapAddr(hwnd, es->hText); strcpy(text, createStruct->lpszName); *(text + es->textlen) = '\0'; - es->textlen = EditBufLen(wndPtr) + 1; } else { @@ -3145,6 +3153,65 @@ LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam) } +/********************************************************************* + * EDIT_CopyToClipboard + * + * Copy the specified text to the clipboard. + */ + +void EDIT_CopyToClipboard(HWND hwnd) +{ + HANDLE hMem; + char *lpMem; + int i, len; + char *bbl, *bel; + WND *wndPtr = WIN_FindWndPtr(hwnd); + EDITSTATE *es = + (EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra))); + + bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol; + bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol; + len = (int)(bel - bbl); + + hMem = GlobalAlloc(GHND, (DWORD)(len + 1)); + lpMem = GlobalLock(hMem); + + for (i = 0; i < len; i++) + *lpMem++ = *bbl++; + + GlobalUnlock(hMem); + OpenClipboard(hwnd); + EmptyClipboard(); + SetClipboardData(CF_TEXT, hMem); + CloseClipboard(); +} + + +/********************************************************************* + * WM_PASTE message function + */ + +void EDIT_PasteMsg(HWND hwnd) +{ + HANDLE hClipMem; + char *lpClipMem; + + OpenClipboard(hwnd); + if (!(hClipMem = GetClipboardData(CF_TEXT))) + { + /* no text in clipboard */ + CloseClipboard(); + return; + } + lpClipMem = GlobalLock(hClipMem); + EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem)); + GlobalUnlock(hClipMem); + CloseClipboard(); + InvalidateRect(hwnd, NULL, TRUE); + UpdateWindow(hwnd); +} + + /********************************************************************* * Utility functions */ diff --git a/controls/menu.c b/controls/menu.c index 18ca83298fb..0f791c757c3 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -3,71 +3,238 @@ */ static char RCSId[] = "$Id$"; static char Copyright[] = "Copyright Martin Ayotte, 1993"; +static char Copyright2[] = "Copyright Alexandre Julliard, 1994"; + +/* + * Note: the style MF_MOUSESELECT is used to mark popup items that + * have been selected, i.e. their popup menu is currently displayed. + * This is probably not the meaning this style has in MS-Windows. + */ /* #define DEBUG_MENU */ +#include #include #include +#include #include "windows.h" #include "syscolor.h" #include "sysmetrics.h" #include "prototypes.h" #include "menu.h" #include "user.h" -#include "heap.h" #include "win.h" - -#define SC_ABOUTWINE SC_SCREENSAVE+1 -#define SC_SYSMENU SC_SCREENSAVE+2 -#define SC_ABOUTWINEDLG SC_SCREENSAVE+3 +#include "message.h" /* Dimension of the menu bitmaps */ static WORD check_bitmap_width = 0, check_bitmap_height = 0; static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0; + /* Flag set by EndMenu() to force an exit from menu tracking */ +static BOOL fEndMenuCalled = FALSE; + /* Space between 2 menu bar items */ #define MENU_BAR_ITEMS_SPACE 16 /* Height of a separator item */ #define SEPARATOR_HEIGHT 5 -extern HINSTANCE hSysRes; -HMENU hSysMenu = 0; -HBITMAP hStdCheck = 0; -HBITMAP hStdMnArrow = 0; -static BOOL MenuHasFocus = FALSE; + /* Values for menu->FocusedItem */ + /* (other values give the position of the focused item) */ +#define NO_SELECTED_ITEM 0xffff +#define SYSMENU_SELECTED 0xfffe /* Only valid on menu-bars */ + +#define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \ + MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR))) + + +extern void NC_DrawSysButton(HWND hwnd, HDC hdc, BOOL down); /* nonclient.c */ +extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor ); /* cursor.c */ + +extern HINSTANCE hSysRes; + +static HMENU hSysMenu = 0; +static HBITMAP hStdCheck = 0; +static HBITMAP hStdMnArrow = 0; -LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd); -LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr); -void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, - BOOL suppress_draw); -BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y); -void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y); -void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y); -void StdDrawPopupMenu(HWND hwnd); -void ResetHiliteFlags(LPPOPUPMENU lppop); -void SelectPrevItem(LPPOPUPMENU lppop); -void SelectNextItem(LPPOPUPMENU lppop); -BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop); -void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex); -LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet); -LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet); -BOOL ActivateMenuBarFocus(HWND hWnd); -BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu); -LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags); -LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos); WORD GetSelectionKey(LPSTR str); LPSTR GetShortCutString(LPSTR str); int GetShortCutPos(LPSTR str); -BOOL HideAllSubPopupMenu(LPPOPUPMENU menu); -void InitStdBitmaps(); HMENU CopySysMenu(); WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu); -void SetMenuLogicalParent(HMENU hMenu, HWND hWnd); -BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam); + +/*********************************************************************** + * MENU_Init + * + * Menus initialisation. + */ +BOOL MENU_Init() +{ + BITMAP bm; + + /* Load bitmaps */ + + if (!(hStdCheck = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECK) ))) + return FALSE; + GetObject( hStdCheck, sizeof(BITMAP), (LPSTR)&bm ); + check_bitmap_width = bm.bmWidth; + check_bitmap_height = bm.bmHeight; + if (!(hStdMnArrow = LoadBitmap( 0, MAKEINTRESOURCE(OBM_MNARROW) ))) + return FALSE; + GetObject( hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm ); + arrow_bitmap_width = bm.bmWidth; + arrow_bitmap_height = bm.bmHeight; + + /* Load system menu */ + + if (!(hSysMenu = LoadMenu( hSysRes, "SYSMENU" ))) + { + printf("SysMenu not found in system resources !\n"); + return FALSE; + } + + return TRUE; +} + + +/*********************************************************************** + * MENU_HasSysMenu + * + * Check whether the window owning the menu bar has a system menu. + */ +static BOOL MENU_HasSysMenu( POPUPMENU *menu ) +{ + WND *wndPtr; + + if (menu->wFlags & MF_POPUP) return FALSE; + if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return FALSE; + return (wndPtr->dwStyle & WS_SYSMENU) != 0; +} + + +/*********************************************************************** + * MENU_IsInSysMenu + * + * Check whether the point (in screen coords) is in the system menu + * of the window owning the given menu. + */ +static BOOL MENU_IsInSysMenu( POPUPMENU *menu, POINT pt ) +{ + WND *wndPtr; + + if (menu->wFlags & MF_POPUP) return FALSE; + if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return FALSE; + if (!(wndPtr->dwStyle & WS_SYSMENU)) return FALSE; + if ((pt.x < wndPtr->rectClient.left) || + (pt.x >= wndPtr->rectClient.left+SYSMETRICS_CXSIZE+SYSMETRICS_CXBORDER)) + return FALSE; + if ((pt.y >= wndPtr->rectClient.top - menu->Height) || + (pt.y < wndPtr->rectClient.top - menu->Height - + SYSMETRICS_CYSIZE - SYSMETRICS_CYBORDER)) return FALSE; + return TRUE; +} + + +/*********************************************************************** + * MENU_FindItem + * + * Find a menu item. Return a pointer on the item, and modifies *hmenu + * in case the item was in a sub-menu. + */ +static MENUITEM *MENU_FindItem( HMENU *hmenu, WORD *nPos, WORD wFlags ) +{ + POPUPMENU *menu; + MENUITEM *item; + int i; + + if (!(menu = (POPUPMENU *) USER_HEAP_ADDR(*hmenu))) return NULL; + item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + if (wFlags & MF_BYPOSITION) + { + if (*nPos >= menu->nItems) return NULL; + return &item[*nPos]; + } + else + { + for (i = 0; i < menu->nItems; i++, item++) + { + if (item->item_id == *nPos) + { + *nPos = i; + return item; + } + else if (item->item_flags & MF_POPUP) + { + HMENU hsubmenu = (HMENU)item->item_id; + MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags ); + if (subitem) + { + *hmenu = hsubmenu; + return subitem; + } + } + } + } + return NULL; +} + + +/*********************************************************************** + * MENU_FindItemByCoords + * + * Find the item at the specified coordinates (screen coords). + */ +static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu, int x, int y, WORD *pos ) +{ + MENUITEM *item; + WND *wndPtr; + int i; + + if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return NULL; + x -= wndPtr->rectWindow.left; + y -= wndPtr->rectWindow.top; + item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + for (i = 0; i < menu->nItems; i++, item++) + { + if ((x >= item->rect.left) && (x < item->rect.right) && + (y >= item->rect.top) && (y < item->rect.bottom)) + { + if (pos) *pos = i; + return item; + } + } + return NULL; +} + + +/*********************************************************************** + * MENU_FindItemByKey + * + * Find the menu item selected by a key press. + * Return item id, -1 if none, -2 if we should close the menu. + */ +static WORD MENU_FindItemByKey( HWND hwndOwner, HMENU hmenu, WORD key ) +{ + POPUPMENU *menu; + LPMENUITEM lpitem; + int i; + LONG menuchar; + + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + lpitem = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + for (i = 0; i < menu->nItems; i++, lpitem++) + { + if (toupper(key) == lpitem->sel_key) return i; + } + menuchar = SendMessage( hwndOwner, WM_MENUCHAR, key, + MAKELONG( menu->wFlags, hmenu ) ); + if (HIWORD(menuchar) == 2) return LOWORD(menuchar); + if (HIWORD(menuchar) == 1) return -2; + return -1; +} /*********************************************************************** @@ -87,7 +254,12 @@ static void MENU_CalcItemSize( HDC hdc, LPMENUITEM lpitem, return; } - if (!menuBar) lpitem->rect.right += check_bitmap_width+arrow_bitmap_width; + if (!menuBar) + { + lpitem->rect.right += 2 * check_bitmap_width; + if (lpitem->item_flags & MF_POPUP) + lpitem->rect.right += arrow_bitmap_width; + } if (lpitem->item_flags & MF_BITMAP) { @@ -113,30 +285,27 @@ static void MENU_CalcItemSize( HDC hdc, LPMENUITEM lpitem, * * Calculate the size of a popup menu. */ -static void MENU_PopupMenuCalcSize( HWND hwnd ) +static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop ) { - LPPOPUPMENU lppop; - LPMENUITEM lpitem, lpitemStart, lptmp; - WND *wndPtr; + LPMENUITEM items, lpitem; HDC hdc; - int orgX, orgY, maxX; + int start, i, orgX, orgY, maxX; - if (!(lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr))) return; - SetRect( &lppop->rect, 0, 0, 0, 0 ); lppop->Width = lppop->Height = 0; if (lppop->nItems == 0) return; - hdc = GetDC( hwnd ); - maxX = 0; - lpitemStart = lppop->firstItem; - while (lpitemStart != NULL) + items = (MENUITEM *)USER_HEAP_ADDR( lppop->hItems ); + hdc = GetDC( 0 ); + maxX = start = 0; + while (start < lppop->nItems) { + lpitem = &items[start]; orgX = maxX; orgY = 0; /* Parse items until column break or end of menu */ - for (lpitem = lpitemStart; lpitem != NULL; lpitem = lpitem->next) + for (i = start; i < lppop->nItems; i++, lpitem++) { - if ((lpitem != lpitemStart) && + if ((i != start) && (lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break; MENU_CalcItemSize( hdc, lpitem, orgX, orgY, FALSE ); maxX = max( maxX, lpitem->rect.right ); @@ -144,19 +313,12 @@ static void MENU_PopupMenuCalcSize( HWND hwnd ) } /* Finish the column (set all items to the largest width found) */ - for (lptmp = lpitemStart; lptmp != lpitem; lptmp = lptmp->next) - { - lptmp->rect.right = maxX; - } - - /* And go to the next column */ + while (start < i) items[start++].rect.right = maxX; lppop->Height = max( lppop->Height, orgY ); - lpitemStart = lpitem; } lppop->Width = maxX; - SetRect( &lppop->rect, 0, 0, lppop->Width, lppop->Height ); - ReleaseDC( hwnd, hdc ); + ReleaseDC( 0, hdc ); } @@ -167,8 +329,8 @@ static void MENU_PopupMenuCalcSize( HWND hwnd ) */ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop ) { - LPMENUITEM lpitem, lpitemStart, lptmp; - int orgX, orgY, maxY; + LPMENUITEM lpitem, items; + int start, i, orgX, orgY, maxY; if ((lprect == NULL) || (lppop == NULL)) return; if (lppop->nItems == 0) return; @@ -176,25 +338,26 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop ) printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n", lprect->left, lprect->top, lprect->right, lprect->bottom); #endif + items = (MENUITEM *)USER_HEAP_ADDR( lppop->hItems ); lppop->Width = lprect->right - lprect->left; lppop->Height = 0; maxY = lprect->top; - - lpitemStart = lppop->firstItem; - while (lpitemStart != NULL) + start = 0; + while (start < lppop->nItems) { + lpitem = &items[start]; orgX = lprect->left; orgY = maxY; /* Parse items until line break or end of menu */ - for (lpitem = lpitemStart; lpitem != NULL; lpitem = lpitem->next) + for (i = start; i < lppop->nItems; i++, lpitem++) { - if ((lpitem != lpitemStart) && + if ((i != start) && (lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break; MENU_CalcItemSize( hdc, lpitem, orgX, orgY, TRUE ); if (lpitem->rect.right > lprect->right) { - if (lpitem != lpitemStart) break; + if (i != start) break; else lpitem->rect.right = lprect->right; } maxY = max( maxY, lpitem->rect.bottom ); @@ -202,18 +365,11 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop ) } /* Finish the line (set all items to the largest height found) */ - for (lptmp = lpitemStart; lptmp != lpitem; lptmp = lptmp->next) - { - lptmp->rect.bottom = maxY; - } - - /* And go to the next line */ - lpitemStart = lpitem; + while (start < i) items[start++].rect.bottom = maxY; } lprect->bottom = maxY; lppop->Height = lprect->bottom - lprect->top; - CopyRect( &lppop->rect, lprect ); } @@ -223,7 +379,7 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop ) * Draw a single menu item. */ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, - LPRECT menuRect, BOOL menuBar ) + WORD height, BOOL menuBar ) { RECT rect; @@ -242,8 +398,8 @@ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, if (!menuBar && (lpitem->item_flags & MF_MENUBARBREAK)) { SelectObject( hdc, sysColorObjects.hpenWindowFrame ); - MoveTo( hdc, rect.left, menuRect->top ); - LineTo( hdc, rect.left, menuRect->bottom ); + MoveTo( hdc, rect.left, 0 ); + LineTo( hdc, rect.left, height ); } if (lpitem->item_flags & MF_SEPARATOR) { @@ -252,6 +408,25 @@ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, LineTo( hdc, rect.right, rect.top + SEPARATOR_HEIGHT/2 ); } + /* Setup colors */ + + if (lpitem->item_flags & MF_HILITE) + { + if (lpitem->item_flags & MF_GRAYED) + SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) ); + else + SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) ); + SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) ); + } + else + { + if (lpitem->item_flags & MF_GRAYED) + SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) ); + else + SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) ); + SetBkColor( hdc, GetSysColor( COLOR_MENU ) ); + } + if (!menuBar) { /* Draw the check mark */ @@ -287,7 +462,7 @@ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, { HDC hMemDC = CreateCompatibleDC( hdc ); SelectObject(hMemDC, hStdMnArrow); - BitBlt( hdc, rect.right-arrow_bitmap_width, + BitBlt( hdc, rect.right-arrow_bitmap_width-1, (rect.top + rect.bottom - arrow_bitmap_height) / 2, arrow_bitmap_width, arrow_bitmap_height, hMemDC, 0, 0, SRCCOPY ); @@ -298,22 +473,6 @@ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, rect.right -= arrow_bitmap_width; } - /* Setup colors */ - - if (lpitem->item_flags & MF_HILITE) - { - SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) ); - SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) ); - } - else - { - if (lpitem->item_flags & MF_GRAYED) - SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) ); - else - SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) ); - SetBkColor( hdc, GetSysColor( COLOR_MENU ) ); - } - /* Draw the item text or bitmap */ if (lpitem->item_flags & MF_BITMAP) @@ -327,7 +486,8 @@ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, DeleteDC( hMemDC ); return; } - else /* No bitmap */ + /* No bitmap - process text if present */ + else if ((lpitem->item_text) != ((char *) NULL)) { int x = GetShortCutPos(lpitem->item_text); if (menuBar) @@ -349,735 +509,869 @@ static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem, /*********************************************************************** - * PopupMenuWndProc + * MENU_DrawPopupMenu + * + * Paint a popup menu. */ -LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam ) -{ - CREATESTRUCT *createStruct; - WORD wRet; - short x, y; - WND *wndPtr; - LPPOPUPMENU lppop, lppop2; - LPMENUITEM lpitem, lpitem2; - HMENU hSubMenu; - RECT rect; - HDC hDC; - PAINTSTRUCT ps; - switch(message) { - case WM_CREATE: -#ifdef DEBUG_MENU - printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam); -#endif - createStruct = (CREATESTRUCT *)lParam; - lppop = (LPPOPUPMENU)createStruct->lpCreateParams; - if (lppop == NULL) break; - wndPtr = WIN_FindWndPtr(hwnd); - *((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop; -#ifdef DEBUG_MENU - printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop); -#endif - InitStdBitmaps(); -#ifdef DEBUG_MENU - printf("PopupMenu End of WM_CREATE !\n"); -#endif - ResetHiliteFlags(lppop); - return 0; - case WM_DESTROY: - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); -#ifdef DEBUG_MENU - printf("PopupMenu WM_DESTROY %lX !\n", lppop); -#endif - return 0; - case WM_COMMAND: -#ifdef DEBUG_MENU - printf("PopupMenuWndProc // WM_COMMAND received !\n"); -#endif - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - if (lppop == NULL) break; - if (lppop->SysFlag) { - MenuHasFocus = FALSE; - if (wParam == SC_ABOUTWINE) { - printf("SysMenu // Show 'About Wine ...' !\n"); -/* DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */ - DialogBox(hSysRes, MAKEINTRESOURCE(2), - GetParent(hwnd), (FARPROC)AboutWine_Proc); - } - else { -#ifdef DEBUG_MENU - printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n"); -#endif - PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam); - } - break; - } -#ifdef DEBUG_MENU - printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n"); -#endif - MenuHasFocus = FALSE; - PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam); - break; - case WM_SHOWWINDOW: -#ifdef DEBUG_MENU - printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n"); -#endif - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - if (lppop == NULL) break; - if (wParam == 0 && lParam == 0L) { - ResetHiliteFlags(lppop); - HideAllSubPopupMenu(lppop); -#ifdef DEBUG_MENU - printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd); -#endif - if (lppop->SysFlag) MenuHasFocus = FALSE; - SetFocus(lppop->hWndPrev); - if (GetCapture() != 0) ReleaseCapture(); - break; - } - lppop->FocusedItem = (WORD)-1; - break; - case WM_LBUTTONDOWN: - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - if (lppop == NULL) break; - SetCapture(hwnd); - MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam)); - break; - case WM_LBUTTONUP: - lppop = PopupMenuGetStorageHeader(hwnd); - if (lppop == NULL) break; - ReleaseCapture(); - MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam)); - break; - case WM_MOUSEMOVE: - lppop = PopupMenuGetStorageHeader(hwnd); - if (lppop == NULL) break; - MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam)); - break; +static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu ) +{ + POPUPMENU *menu; + MENUITEM *item; + RECT rect; + int i; - case WM_KEYUP: -#ifdef DEBUG_MENU - printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n", - hwnd, wParam, lParam); -#endif - break; - case WM_KEYDOWN: -#ifdef DEBUG_MENU - printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n", - hwnd, wParam, lParam); -#endif - if (lParam < 0L) break; - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - if (lppop == NULL) break; - switch(wParam) { - case VK_HOME: - if (lppop->FocusedItem == 0) break; - MenuItemSelect(hwnd, lppop, 0); - break; - case VK_UP: - if (lppop->BarFlag) break; - SelectPrevItem(lppop); - break; - case VK_DOWN: - if (lppop->BarFlag) goto ProceedSPACE; - SelectNextItem(lppop); - break; - case VK_LEFT: - if (lppop->SysFlag != 0) { - ShowWindow(hwnd, SW_HIDE); - hwnd = lppop->hWndParent; - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - printf("VK_LEFT // try to put focus on MenuBar %08X !\n", lppop); - if (lppop == NULL) break; - MenuItemSelect(hwnd, lppop, lppop->nItems - 1); - break; - } - if (lppop->BarFlag) { - if (lppop->FocusedItem < 1) { - MenuItemSelect(hwnd, lppop, -1); - NC_TrackSysMenu(hwnd); - break; - } - if (HideAllSubPopupMenu(lppop)) { - MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1); - goto ProceedSPACE; - } - } - if (lppop->hWndParent != 0) { - PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam); - break; - } - MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1); - break; - case VK_RIGHT: - if (lppop->SysFlag != 0) { - ShowWindow(hwnd, SW_HIDE); - hwnd = lppop->hWndParent; - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - printf("VK_RIGHT // try to put focus on MenuBar %08X !\n", lppop); - if (lppop == NULL) break; - MenuItemSelect(hwnd, lppop, 0); - break; - } - if (lppop->BarFlag) { - if (lppop->FocusedItem >= lppop->nItems - 1) { - MenuItemSelect(hwnd, lppop, -1); - NC_TrackSysMenu(hwnd); - break; - } - if (HideAllSubPopupMenu(lppop)) { - MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1); - goto ProceedSPACE; - } - } - if (lppop->hWndParent != 0) { - PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam); - break; - } - MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1); - break; - default: - break; - } - break; - case WM_CHAR: -#ifdef DEBUG_MENU - printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam); -#endif - if (lParam < 0L) break; - hwnd = GetFocus(); - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - if (lppop == NULL) break; - switch(wParam) { - case VK_RETURN: - case VK_SPACE: -ProceedSPACE: lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - ExecFocusedMenuItem(hwnd, lppop); - break; - case VK_ESCAPE: - if (lppop->BarFlag) { -#ifdef DEBUG_MENU - printf("VK_ESCAPE // Unselect all MenuBar's Items !\n"); -#endif - if (lppop->FocusedItem != (WORD)-1) - MenuItemSelect(hwnd, lppop, -1); - } - if (lppop->SysFlag) { -#ifdef DEBUG_MENU - printf("VK_ESCAPE // SysMenu !\n"); -#endif - ShowWindow(hwnd, SW_HIDE); - break; - } - if (lppop->hWndParent != 0) { -#ifdef DEBUG_MENU - printf("VK_ESCAPE // Hide only SubPopup !\n"); -#endif - lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr); - if (lppop2 == NULL) break; - HideAllSubPopupMenu(lppop2); - break; - } - else { -#ifdef DEBUG_MENU - printf("VK_ESCAPE // Hide Root Popup !\n"); -#endif - ShowWindow(hwnd, SW_HIDE); - MenuHasFocus = FALSE; - } - break; - default: - if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A'; - lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet); - if (lpitem != NULL) { - printf("ShortKey Found wRet=%d !\n", wRet); - MenuItemSelect(hwnd, lppop, wRet); - lppop->FocusedItem = wRet; - goto ProceedSPACE; - } - printf("ShortKey Not Found wParam=%04X wRet=%d lpitem=%08X !\n", - wParam, wRet, lpitem); - if (lppop->hWndParent != (HWND)NULL) - SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam, - MAKELONG(0, 0)); - else - SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam, - MAKELONG(0, 0)); - break; - } - break; - case WM_PAINT: -#ifdef DEBUG_MENU - printf("PopupMenuWndProc // WM_PAINT received !\n"); -#endif - StdDrawPopupMenu(hwnd); - break; - default: - return DefWindowProc(hwnd, message, wParam, lParam); - } -return 0; + GetClientRect( hwnd, &rect ); + FillRect( hdc, &rect, sysColorObjects.hbrushMenu ); + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (!menu || !menu->nItems) return; + item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + for (i = menu->nItems; i > 0; i--, item++) + MENU_DrawMenuItem( hdc, item, menu->Height, FALSE ); } -BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop) -{ - short x, y; - LPPOPUPMENU lppop2; - LPMENUITEM lpitem; - HMENU hSubMenu; - RECT rect; - lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem); - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) { - hSubMenu = (HMENU)lpitem->item_id; - lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu); - if (lppop2 == NULL) return FALSE; - lppop2->hWndParent = hWnd; - GetClientRect(hWnd, &rect); - if (lppop->BarFlag) { - GetWindowRect(hWnd, &rect); - y = rect.top + lpitem->rect.bottom; - TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, - rect.left + lpitem->rect.left, - y, 0, lppop->ownerWnd, (LPRECT)NULL); - } - else { - x = lppop->rect.right; - GetWindowRect(hWnd, &rect); - x += rect.left; - TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, - x, rect.top + lpitem->rect.top, - 0, lppop->ownerWnd, (LPRECT)NULL); - } - GlobalUnlock(hSubMenu); - return TRUE; - } - if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) && - ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) { - MenuHasFocus = FALSE; - if (lppop->BarFlag) { - PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L); - } - else { - ShowWindow(lppop->hWnd, SW_HIDE); - SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L); - } - } - return TRUE; -} - - - -BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y) -{ - HDC hDC; - LPMENUITEM lpitem, lpitem2; - RECT rect; - HMENU hSubMenu; - WORD wRet; - LPPOPUPMENU lppop2; - if (lppop == NULL) return; - lpitem = MenuFindItem(lppop, x, y, &wRet); -#ifdef DEBUG_MENU - printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n", - hWnd, x, y, wRet, lpitem); -#endif - if (lpitem != NULL) { - if (lppop->FocusedItem != (WORD)-1 && wRet == lppop->FocusedItem) { - lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem); - if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) { - hSubMenu = (HMENU)lpitem2->item_id; - lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu); - if (lppop2 == NULL) return FALSE; - if (IsWindowVisible(lppop2->hWnd)) { - ShowWindow(lppop2->hWnd, SW_HIDE); - return TRUE; - } - } - } - MenuItemSelect(hWnd, lppop, wRet); - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) { - hSubMenu = (HMENU)lpitem->item_id; - lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu); - if (lppop2 == NULL) return FALSE; - lppop2->hWndParent = hWnd; - if (lppop->BarFlag) { - GetWindowRect(hWnd, &rect); - y = rect.top + lpitem->rect.bottom; - ReleaseCapture(); - if (MenuHasFocus) { - TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, - rect.left + lpitem->rect.left, - y, 0, lppop->ownerWnd, (LPRECT)NULL); - } - else { - MenuHasFocus = TRUE; - TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, - rect.left + lpitem->rect.left, - y, 0, lppop->ownerWnd, (LPRECT)NULL); - MenuHasFocus = FALSE; - MenuFocusLoop(hWnd, lppop); - return TRUE; - } - } - else { - x = lppop->rect.right; - GetWindowRect(hWnd, &rect); - x += rect.left; - TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, - x, rect.top + lpitem->rect.top, - 0, lppop->ownerWnd, (LPRECT)NULL); - } - GlobalUnlock(hSubMenu); - return TRUE; - } - if (lppop->BarFlag && !MenuHasFocus) { - MenuFocusLoop(hWnd, lppop); - } - return TRUE; - } - printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y); - if (GetCapture() != 0) ReleaseCapture(); - MenuHasFocus = FALSE; - ShowWindow(lppop->hWnd, SW_HIDE); - return FALSE; -} - - - -void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y) -{ - HDC hDC; - LPMENUITEM lpitem, lpitem2; - RECT rect; - HMENU hSubMenu; - WORD wRet; - LPPOPUPMENU lppop2; - if (lppop == NULL) return; - lpitem = MenuFindItem(lppop, x, y, &wRet); -#ifdef DEBUG_MENU - printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n", - x, y, wRet, lpitem); -#endif - if (lpitem != NULL) { - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) { - return; - } - if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) && - ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) { - MenuHasFocus = FALSE; - if (lppop->BarFlag) { - PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L); - } - else { - ShowWindow(lppop->hWnd, SW_HIDE); - SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L); - } - return; - } - } - if (lppop->FocusedItem != (WORD)-1) { - MenuItemSelect(hWnd, lppop, lppop->FocusedItem); - } -} - - - -void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y) -{ - HDC hDC; - RECT rect; - HMENU hSubMenu; - LPMENUITEM lpitem, lpitem2; - LPPOPUPMENU lppop2; - WORD wRet; - - if (GetKeyState(VK_LBUTTON) != 0) - { - lpitem = MenuFindItem(lppop, x, y, &wRet); -#ifdef DEBUG_MENU - printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n", - x, y, wRet, lpitem); -#endif - if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) - { - lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem); - hDC = GetWindowDC(hWnd); - if ((lpitem2 != NULL ) && - (lpitem2->item_flags & MF_POPUP) == MF_POPUP) - { - HideAllSubPopupMenu(lppop); - } - MenuItemSelect(hWnd, lppop, wRet); - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) - { - hSubMenu = (HMENU)lpitem->item_id; - lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu); - if (lppop2 == NULL) - { - ReleaseDC(hWnd, hDC); - return; - } - if (lppop->BarFlag) - { - lppop2->hWndParent = hWnd; - GetWindowRect(hWnd, &rect); - rect.top += lpitem->rect.bottom; - TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, - rect.left + lpitem->rect.left, rect.top, - 0, lppop->ownerWnd, (LPRECT)NULL); - } - GlobalUnlock(hSubMenu); - } - ReleaseDC(hWnd, hDC); - } - } -} - - -void SelectPrevItem(LPPOPUPMENU lppop) -{ - int nIndex; - LPMENUITEM lpitem; - if (lppop == NULL) return; - nIndex = lppop->FocusedItem; - if (nIndex < 1) { - if (nIndex == -1) - nIndex = 0; - else - nIndex = lppop->nItems - 1; - lpitem = GetMenuItemPtr(lppop, nIndex); - } - else { - nIndex--; - lpitem = GetMenuItemPtr(lppop, nIndex); - } - while (lpitem != NULL && lpitem->item_flags & MF_SEPARATOR) { - nIndex--; - lpitem = GetMenuItemPtr(lppop, nIndex); - } - MenuItemSelect(lppop->hWnd, lppop, nIndex); -} - - -void SelectNextItem(LPPOPUPMENU lppop) -{ - int nIndex; - LPMENUITEM lpitem; - if (lppop == NULL) return; - nIndex = lppop->FocusedItem; - if ((nIndex == -1) || (nIndex >= lppop->nItems - 1)) { - nIndex = 0; - lpitem = GetMenuItemPtr(lppop, nIndex); - } - else { - nIndex++; - lpitem = GetMenuItemPtr(lppop, nIndex); - } - while (lpitem != NULL && (lpitem->item_flags & MF_SEPARATOR)) { - nIndex++; - lpitem = GetMenuItemPtr(lppop, nIndex); - } - MenuItemSelect(lppop->hWnd, lppop, nIndex); -} - - -void ResetHiliteFlags(LPPOPUPMENU lppop) -{ - LPMENUITEM lpitem; - int i; -#ifdef DEBUG_MENU - printf("ResetHiliteFlags lppop=%08X\n", lppop); -#endif - if (lppop == NULL) return; - lpitem = lppop->firstItem; - for(i = 0; i < lppop->nItems; i++) { - if (lpitem == NULL) return; - lpitem->item_flags &= ~MF_HILITE; - lpitem = (LPMENUITEM)lpitem->next; - } -} - - -void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex) +/*********************************************************************** + * MENU_DrawMenuBar + * + * Paint a menu bar. Returns the height of the menu bar. + */ +WORD MENU_DrawMenuBar(HDC hDC, LPRECT lprect, HMENU hmenu, BOOL suppress_draw) { + LPPOPUPMENU lppop; LPMENUITEM lpitem; + int i; + + lppop = (LPPOPUPMENU) USER_HEAP_ADDR( hmenu ); + if (lppop == NULL || lprect == NULL) return SYSMETRICS_CYMENU; +#ifdef DEBUG_MENU + printf("MENU_DrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop); +#endif + if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop); + if (suppress_draw) return lppop->Height; + + FillRect(hDC, lprect, sysColorObjects.hbrushMenu ); + SelectObject( hDC, sysColorObjects.hpenWindowFrame ); + MoveTo( hDC, lprect->left, lprect->bottom ); + LineTo( hDC, lprect->right, lprect->bottom ); + + if (lppop->nItems == 0) return SYSMETRICS_CYMENU; + lpitem = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems ); + for (i = 0; i < lppop->nItems; i++, lpitem++) + { + MENU_DrawMenuItem( hDC, lpitem, lppop->Height, TRUE ); + } + return lppop->Height; +} + + +/*********************************************************************** + * MENU_ShowPopup + * + * Display a popup menu. + */ +static BOOL MENU_ShowPopup(HWND hwndOwner, HMENU hmenu, WORD id, int x, int y) +{ + POPUPMENU *menu; + + if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return FALSE; + if (menu->FocusedItem != NO_SELECTED_ITEM) + { + MENUITEM *item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + item[menu->FocusedItem].item_flags &= ~(MF_HILITE | MF_MOUSESELECT); + menu->FocusedItem = NO_SELECTED_ITEM; + } + SendMessage( hwndOwner, WM_INITMENUPOPUP, hmenu, + MAKELONG( id, (menu->wFlags & MF_POPUP) ? 1 : 0 )); + MENU_PopupMenuCalcSize( menu ); + if (!menu->hWnd) + { + WND *wndPtr = WIN_FindWndPtr( hwndOwner ); + if (!wndPtr) return FALSE; + menu->hWnd = CreateWindow( POPUPMENU_CLASS_NAME, "", + WS_POPUP | WS_BORDER, x, y, + menu->Width + 2*SYSMETRICS_CXBORDER, + menu->Height + 2*SYSMETRICS_CYBORDER, + 0, 0, wndPtr->hInstance, + (LPSTR)(DWORD)hmenu ); + if (!menu->hWnd) return FALSE; + } + else SetWindowPos( menu->hWnd, 0, x, y, + menu->Width + 2*SYSMETRICS_CXBORDER, + menu->Height + 2*SYSMETRICS_CYBORDER, + SWP_NOACTIVATE | SWP_NOZORDER ); + + /* Display the window */ + + SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0, + SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); + UpdateWindow( menu->hWnd ); + return TRUE; +} + + +/*********************************************************************** + * MENU_SelectItem + */ +static void MENU_SelectItem( HMENU hmenu, WORD wIndex ) +{ + MENUITEM *items; + LPPOPUPMENU lppop; HDC hdc; - if (lppop == NULL) return; - if (lppop->BarFlag) hdc = GetDCEx( hWnd, 0, DCX_CACHE | DCX_WINDOW ); - else hdc = GetDC( hWnd ); + lppop = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (!lppop->nItems) return; + items = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems ); + if ((wIndex != NO_SELECTED_ITEM) && + (wIndex != SYSMENU_SELECTED) && + (items[wIndex].item_flags & MF_SEPARATOR)) + wIndex = NO_SELECTED_ITEM; + if (lppop->FocusedItem == wIndex) return; + if (lppop->wFlags & MF_POPUP) hdc = GetDC( lppop->hWnd ); + else hdc = GetDCEx( lppop->hWnd, 0, DCX_CACHE | DCX_WINDOW); /* Clear previous highlighted item */ - if (lppop->FocusedItem != (WORD)-1) + if (lppop->FocusedItem != NO_SELECTED_ITEM) { - if ((lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem)) != NULL) + if (lppop->FocusedItem == SYSMENU_SELECTED) + NC_DrawSysButton( lppop->hWnd, hdc, FALSE ); + else { - lpitem->item_flags &= ~MF_HILITE; - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) - HideAllSubPopupMenu(lppop); - MENU_DrawMenuItem( hdc, lpitem, &lppop->rect, lppop->BarFlag ); + items[lppop->FocusedItem].item_flags &=~(MF_HILITE|MF_MOUSESELECT); + MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height, + !(lppop->wFlags & MF_POPUP) ); } } /* Highlight new item (if any) */ lppop->FocusedItem = wIndex; - if (lppop->FocusedItem != (WORD)-1) + if (lppop->FocusedItem != NO_SELECTED_ITEM) { - if ((lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem)) != NULL) + if (lppop->FocusedItem == SYSMENU_SELECTED) + NC_DrawSysButton( lppop->hWnd, hdc, TRUE ); + else { - lpitem->item_flags |= MF_HILITE; - MENU_DrawMenuItem( hdc, lpitem, &lppop->rect, lppop->BarFlag ); - SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id, - MAKELONG(0, lpitem->item_flags)); + items[lppop->FocusedItem].item_flags |= MF_HILITE; + MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height, + !(lppop->wFlags & MF_POPUP) ); + SendMessage(lppop->hWnd, WM_MENUSELECT, + items[lppop->FocusedItem].item_id, + MAKELONG( hmenu, items[lppop->FocusedItem].item_flags)); } } - ReleaseDC( hWnd, hdc ); + ReleaseDC( lppop->hWnd, hdc ); } -LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr) +/*********************************************************************** + * MENU_SelectNextItem + */ +static void MENU_SelectNextItem( HMENU hmenu ) { - WND *Ptr; - LPPOPUPMENU lppop; - *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd); - if (Ptr == 0) { - printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n"); - return NULL; - } - lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]); - if (lppop == NULL) { - lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu); - if (lppop == NULL) { - printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n"); - return NULL; - } - } - return lppop; -} + int i; + MENUITEM *items; + POPUPMENU *menu; - -LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd) -{ - WND *Ptr; - LPPOPUPMENU lppop; - Ptr = WIN_FindWndPtr(hwnd); - if (Ptr == 0) { - printf("Bad Window handle on PopupMenu !\n"); - return 0; - } - lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]); - return lppop; -} - - -void SetMenuLogicalParent(HMENU hMenu, HWND hWnd) -{ - LPPOPUPMENU lppop; - lppop = (LPPOPUPMENU)GlobalLock(hMenu); - lppop->hWndParent = hWnd; - GlobalUnlock(hMenu); -} - - -void StdDrawPopupMenu(HWND hwnd) -{ - WND *wndPtr; - LPPOPUPMENU lppop; - LPMENUITEM lpitem; - PAINTSTRUCT ps; - RECT rect; - HDC hDC; - - hDC = BeginPaint(hwnd, &ps); - GetClientRect(hwnd, &rect); - FillRect(hDC, &rect, sysColorObjects.hbrushMenu ); - - lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr); - for (lpitem = lppop->firstItem; lpitem != NULL; lpitem = lpitem->next ) + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (!menu->nItems) return; + items = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + if ((menu->FocusedItem != NO_SELECTED_ITEM) && + (menu->FocusedItem != SYSMENU_SELECTED)) + { + for (i = menu->FocusedItem+1; i < menu->nItems; i++) { - MENU_DrawMenuItem( hDC, lpitem, &rect, FALSE ); + if (!(items[i].item_flags & MF_SEPARATOR)) + { + MENU_SelectItem( hmenu, i ); + return; + } } - EndPaint( hwnd, &ps ); + if (MENU_HasSysMenu( menu )) + { + MENU_SelectItem( hmenu, SYSMENU_SELECTED ); + return; + } + } + for (i = 0; i < menu->nItems; i++) + { + if (!(items[i].item_flags & MF_SEPARATOR)) + { + MENU_SelectItem( hmenu, i ); + return; + } + } + if (MENU_HasSysMenu( menu )) MENU_SelectItem( hmenu, SYSMENU_SELECTED ); } -void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, - BOOL suppress_draw) +/*********************************************************************** + * MENU_SelectPrevItem + */ +static void MENU_SelectPrevItem( HMENU hmenu ) { - LPMENUITEM lpitem; - if (lppop == NULL || lprect == NULL) return; + int i; + MENUITEM *items; + POPUPMENU *menu; + + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (!menu->nItems) return; + items = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + if ((menu->FocusedItem != NO_SELECTED_ITEM) && + (menu->FocusedItem != SYSMENU_SELECTED)) + { + for (i = menu->FocusedItem - 1; i >= 0; i--) + { + if (!(items[i].item_flags & MF_SEPARATOR)) + { + MENU_SelectItem( hmenu, i ); + return; + } + } + if (MENU_HasSysMenu( menu )) + { + MENU_SelectItem( hmenu, SYSMENU_SELECTED ); + return; + } + } + for (i = menu->nItems - 1; i > 0; i--) + { + if (!(items[i].item_flags & MF_SEPARATOR)) + { + MENU_SelectItem( hmenu, i ); + return; + } + } + if (MENU_HasSysMenu( menu )) MENU_SelectItem( hmenu, SYSMENU_SELECTED ); +} + + +/*********************************************************************** + * MENU_GetSubPopup + * + * Return the handle of the selected sub-popup menu (if any). + */ +static HMENU MENU_GetSubPopup( HMENU hmenu ) +{ + POPUPMENU *menu; + MENUITEM *item; + + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (menu->FocusedItem == NO_SELECTED_ITEM) return 0; + else if (menu->FocusedItem == SYSMENU_SELECTED) + return GetSystemMenu( menu->hWnd, FALSE ); + + item = ((MENUITEM *)USER_HEAP_ADDR( menu->hItems )) + menu->FocusedItem; + if (!(item->item_flags & MF_POPUP) || !(item->item_flags & MF_MOUSESELECT)) + return 0; + return item->item_id; +} + + +/*********************************************************************** + * MENU_HideSubPopups + * + * Hide the sub-popup menus of this menu. + */ +static void MENU_HideSubPopups( HMENU hmenu ) +{ + MENUITEM *item; + POPUPMENU *menu, *submenu; + HMENU hsubmenu; + + if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return; + if (menu->FocusedItem == NO_SELECTED_ITEM) return; + if (menu->FocusedItem == SYSMENU_SELECTED) + { + hsubmenu = GetSystemMenu( menu->hWnd, FALSE ); + } + else + { + item = ((MENUITEM *)USER_HEAP_ADDR(menu->hItems)) + menu->FocusedItem; + if (!(item->item_flags & MF_POPUP) || + !(item->item_flags & MF_MOUSESELECT)) return; + item->item_flags &= ~MF_MOUSESELECT; + hsubmenu = item->item_id; + } + submenu = (POPUPMENU *) USER_HEAP_ADDR( hsubmenu ); + MENU_HideSubPopups( hsubmenu ); + if (submenu->hWnd) ShowWindow( submenu->hWnd, SW_HIDE ); + MENU_SelectItem( hsubmenu, NO_SELECTED_ITEM ); +} + + +/*********************************************************************** + * MENU_ShowSubPopup + * + * Display the sub-menu of the selected item of this menu. + * Return the handle of the submenu, or hmenu if no submenu to display. + */ +static HMENU MENU_ShowSubPopup( HWND hwndOwner, HMENU hmenu, BOOL selectFirst ) +{ + POPUPMENU *menu; + MENUITEM *item; + WND *wndPtr; + + if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return hmenu; + if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return hmenu; + if (menu->FocusedItem == NO_SELECTED_ITEM) return hmenu; + if (menu->FocusedItem == SYSMENU_SELECTED) + { + MENU_ShowPopup(hwndOwner, wndPtr->hSysMenu, 0, wndPtr->rectClient.left, + wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER); + if (selectFirst) MENU_SelectNextItem( wndPtr->hSysMenu ); + return wndPtr->hSysMenu; + } + item = ((MENUITEM *)USER_HEAP_ADDR( menu->hItems )) + menu->FocusedItem; + if (!(item->item_flags & MF_POPUP) || + (item->item_flags & (MF_GRAYED | MF_DISABLED))) return hmenu; + item->item_flags |= MF_MOUSESELECT; + if (menu->wFlags & MF_POPUP) + { + MENU_ShowPopup( hwndOwner, (HMENU)item->item_id, menu->FocusedItem, + wndPtr->rectWindow.left + item->rect.right-arrow_bitmap_width, + wndPtr->rectWindow.top + item->rect.top ); + } + else + { + MENU_ShowPopup( hwndOwner, (HMENU)item->item_id, menu->FocusedItem, + wndPtr->rectWindow.left + item->rect.left, + wndPtr->rectWindow.top + item->rect.bottom ); + } + if (selectFirst) MENU_SelectNextItem( (HMENU)item->item_id ); + return (HMENU)item->item_id; +} + + +/*********************************************************************** + * MENU_FindMenuByCoords + * + * Find the menu containing a given point (in screen coords). + */ +static HMENU MENU_FindMenuByCoords( HMENU hmenu, POINT pt ) +{ + POPUPMENU *menu; + HWND hwnd; + + if (!(hwnd = WindowFromPoint( pt ))) return 0; + while (hmenu) + { + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (menu->hWnd == hwnd) + { + if (!(menu->wFlags & MF_POPUP)) + { + /* Make sure it's in the menu bar (or in system menu) */ + WND *wndPtr = WIN_FindWndPtr( menu->hWnd ); + if ((pt.x < wndPtr->rectClient.left) || + (pt.x >= wndPtr->rectClient.right) || + (pt.y >= wndPtr->rectClient.top)) return 0; + if (pt.y < wndPtr->rectClient.top - menu->Height) + { + if (!MENU_IsInSysMenu( menu, pt )) return 0; + } + /* else it's in the menu bar */ + } + return hmenu; + } + hmenu = MENU_GetSubPopup( hmenu ); + } + return 0; +} + + +/*********************************************************************** + * MENU_ExecFocusedItem + * + * Execute a menu item (for instance when user pressed Enter). + * Return TRUE if we can go on with menu tracking. + */ +static BOOL MENU_ExecFocusedItem( HWND hwndOwner, HMENU hmenu, + HMENU *hmenuCurrent ) +{ + MENUITEM *item; + POPUPMENU *menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + if (!menu || !menu->nItems || (menu->FocusedItem == NO_SELECTED_ITEM) || + (menu->FocusedItem == SYSMENU_SELECTED)) return TRUE; + item = ((MENUITEM *)USER_HEAP_ADDR( menu->hItems )) + menu->FocusedItem; + if (!(item->item_flags & MF_POPUP)) + { + if (!(item->item_flags & (MF_GRAYED | MF_DISABLED))) + { + PostMessage( hwndOwner, (menu->wFlags & MF_SYSMENU) ? + WM_SYSCOMMAND : WM_COMMAND, item->item_id, 0 ); + return FALSE; + } + else return TRUE; + } + else + { + *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, TRUE ); + return TRUE; + } +} + + +/*********************************************************************** + * MENU_ButtonDown + * + * Handle a button-down event in a menu. Point is in screen coords. + * hmenuCurrent is the top-most visible popup. + * Return TRUE if we can go on with menu tracking. + */ +static BOOL MENU_ButtonDown( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent, + POINT pt ) +{ + POPUPMENU *menu; + MENUITEM *item; + WORD id; + + if (!hmenu) return FALSE; /* Outside all menus */ + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + item = MENU_FindItemByCoords( menu, pt.x, pt.y, &id ); + if (!item) /* Maybe in system menu */ + { + if (!MENU_IsInSysMenu( menu, pt )) return FALSE; + id = SYSMENU_SELECTED; + } + + if (menu->FocusedItem == id) + { + if (id == SYSMENU_SELECTED) return FALSE; + if (item->item_flags & MF_POPUP) + { + if (item->item_flags & MF_MOUSESELECT) + { + if (menu->wFlags & MF_POPUP) + { + MENU_HideSubPopups( hmenu ); + *hmenuCurrent = hmenu; + } + else return FALSE; + } + else *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE ); + } + } + else + { + MENU_HideSubPopups( hmenu ); + MENU_SelectItem( hmenu, id ); + *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE ); + } + return TRUE; +} + + +/*********************************************************************** + * MENU_ButtonUp + * + * Handle a button-up event in a menu. Point is in screen coords. + * hmenuCurrent is the top-most visible popup. + * Return TRUE if we can go on with menu tracking. + */ +static BOOL MENU_ButtonUp( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent, + POINT pt ) +{ + POPUPMENU *menu; + MENUITEM *item; + HMENU hsubmenu; + WORD id; + + if (!hmenu) return FALSE; /* Outside all menus */ + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + item = MENU_FindItemByCoords( menu, pt.x, pt.y, &id ); + if (!item) /* Maybe in system menu */ + { + if (!MENU_IsInSysMenu( menu, pt )) return FALSE; + id = SYSMENU_SELECTED; + hsubmenu = GetSystemMenu( menu->hWnd, FALSE ); + } + + if (menu->FocusedItem != id) return FALSE; + + if (id != SYSMENU_SELECTED) + { + if (!(item->item_flags & MF_POPUP)) + { + return MENU_ExecFocusedItem( hwndOwner, hmenu, hmenuCurrent ); + } + hsubmenu = item->item_id; + } + /* Select first item of sub-popup */ + MENU_SelectItem( hsubmenu, NO_SELECTED_ITEM ); + MENU_SelectNextItem( hsubmenu ); + return TRUE; +} + + +/*********************************************************************** + * MENU_MouseMove + * + * Handle a motion event in a menu. Point is in screen coords. + * hmenuCurrent is the top-most visible popup. + * Return TRUE if we can go on with menu tracking. + */ +static BOOL MENU_MouseMove( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent, + POINT pt ) +{ + POPUPMENU *menu; + MENUITEM *item; + WORD id = NO_SELECTED_ITEM; + + if (hmenu) + { + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + item = MENU_FindItemByCoords( menu, pt.x, pt.y, &id ); + if (!item) /* Maybe in system menu */ + { + if (!MENU_IsInSysMenu( menu, pt )) + id = NO_SELECTED_ITEM; /* Outside all items */ + else id = SYSMENU_SELECTED; + } + } + if (id == NO_SELECTED_ITEM) + { + MENU_SelectItem( *hmenuCurrent, NO_SELECTED_ITEM ); + } + else if (menu->FocusedItem != id) + { + MENU_HideSubPopups( hmenu ); + MENU_SelectItem( hmenu, id ); + *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, FALSE ); + } + return TRUE; +} + + +/*********************************************************************** + * MENU_KeyLeft + * + * Handle a VK_LEFT key event in a menu. + * hmenuCurrent is the top-most visible popup. + */ +static void MENU_KeyLeft( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent ) +{ + POPUPMENU *menu; + HMENU hmenutmp, hmenuprev; + + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + hmenuprev = hmenutmp = hmenu; + while (hmenutmp != *hmenuCurrent) + { + hmenutmp = MENU_GetSubPopup( hmenuprev ); + if (hmenutmp != *hmenuCurrent) hmenuprev = hmenutmp; + } + MENU_HideSubPopups( hmenuprev ); + + if ((hmenuprev == hmenu) && !(menu->wFlags & MF_POPUP)) + { + /* Select previous item on the menu bar */ + MENU_SelectPrevItem( hmenu ); + if (*hmenuCurrent != hmenu) + { + /* A popup menu was displayed -> display the next one */ + *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, TRUE ); + } + } + else *hmenuCurrent = hmenuprev; +} + + +/*********************************************************************** + * MENU_KeyRight + * + * Handle a VK_RIGHT key event in a menu. + * hmenuCurrent is the top-most visible popup. + */ +static void MENU_KeyRight( HWND hwndOwner, HMENU hmenu, HMENU *hmenuCurrent ) +{ + POPUPMENU *menu; + HMENU hmenutmp; + + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + + if ((menu->wFlags & MF_POPUP) || (*hmenuCurrent != hmenu)) + { + /* If already displaying a popup, try to display sub-popup */ + hmenutmp = MENU_ShowSubPopup( hwndOwner, *hmenuCurrent, TRUE ); + if (hmenutmp != *hmenuCurrent) /* Sub-popup displayed */ + { + *hmenuCurrent = hmenutmp; + return; + } + } + + /* If on menu-bar, go to next item */ + if (!(menu->wFlags & MF_POPUP)) + { + MENU_HideSubPopups( hmenu ); + MENU_SelectNextItem( hmenu ); + if (*hmenuCurrent != hmenu) + { + /* A popup menu was displayed -> display the next one */ + *hmenuCurrent = MENU_ShowSubPopup( hwndOwner, hmenu, TRUE ); + } + } + else if (*hmenuCurrent != hmenu) /* Hide last level popup */ + { + HMENU hmenuprev; + hmenuprev = hmenutmp = hmenu; + while (hmenutmp != *hmenuCurrent) + { + hmenutmp = MENU_GetSubPopup( hmenuprev ); + if (hmenutmp != *hmenuCurrent) hmenuprev = hmenutmp; + } + MENU_HideSubPopups( hmenuprev ); + *hmenuCurrent = hmenuprev; + } +} + + +/*********************************************************************** + * MENU_TrackMenu + * + * Menu tracking code. + * If 'x' and 'y' are not 0, we simulate a button-down event at (x,y) + * before beginning tracking. This is to help menu-bar tracking. + */ +static BOOL MENU_TrackMenu( HMENU hmenu, WORD wFlags, int x, int y, + HWND hwnd, LPRECT lprect ) +{ + MSG msg; + POPUPMENU *menu; + HMENU hmenuCurrent = hmenu; + BOOL fClosed = FALSE; + WORD pos; + + fEndMenuCalled = FALSE; + if (!(menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ))) return FALSE; + if (x && y) + { + POINT pt = { x, y }; + MENU_ButtonDown( hwnd, hmenu, &hmenuCurrent, pt ); + } + SetCapture( hwnd ); + + while (!fClosed) + { + if (!MSG_InternalGetMessage( &msg, 0, hwnd, MSGF_MENU, 0, TRUE )) + break; + + if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST)) + { + /* Find the sub-popup for this mouse event (if any) */ + HMENU hsubmenu = MENU_FindMenuByCoords( hmenu, msg.pt ); + + switch(msg.message) + { + case WM_RBUTTONDOWN: + case WM_NCRBUTTONDOWN: + if (!(wFlags & TPM_RIGHTBUTTON)) break; + /* fall through */ + case WM_LBUTTONDOWN: + case WM_NCLBUTTONDOWN: + fClosed = !MENU_ButtonDown( hwnd, hsubmenu, + &hmenuCurrent, msg.pt ); + break; + + case WM_RBUTTONUP: + case WM_NCRBUTTONUP: + if (!(wFlags & TPM_RIGHTBUTTON)) break; + /* fall through */ + case WM_LBUTTONUP: + case WM_NCLBUTTONUP: + /* If outside all menus but inside lprect, ignore it */ + if (!hsubmenu && lprect && PtInRect( lprect, msg.pt )) break; + fClosed = !MENU_ButtonUp( hwnd, hsubmenu, + &hmenuCurrent, msg.pt ); + break; + + case WM_MOUSEMOVE: + case WM_NCMOUSEMOVE: + if ((msg.wParam & MK_LBUTTON) || + ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON))) + { + fClosed = !MENU_MouseMove( hwnd, hsubmenu, + &hmenuCurrent, msg.pt ); + } + break; + } + } + else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST)) + { + switch(msg.message) + { + case WM_KEYDOWN: + switch(msg.wParam) + { + case VK_HOME: + MENU_SelectItem( hmenuCurrent, NO_SELECTED_ITEM ); + MENU_SelectNextItem( hmenuCurrent ); + break; + + case VK_END: + MENU_SelectItem( hmenuCurrent, NO_SELECTED_ITEM ); + MENU_SelectPrevItem( hmenuCurrent ); + break; + + case VK_UP: + MENU_SelectPrevItem( hmenuCurrent ); + break; + + case VK_DOWN: + /* If on menu bar, pull-down the menu */ + if (!(menu->wFlags & MF_POPUP) && (hmenuCurrent == hmenu)) + hmenuCurrent = MENU_ShowSubPopup( hwnd, hmenu, TRUE ); + else + MENU_SelectNextItem( hmenuCurrent ); + break; + + case VK_LEFT: + MENU_KeyLeft( hwnd, hmenu, &hmenuCurrent ); + break; + + case VK_RIGHT: + MENU_KeyRight( hwnd, hmenu, &hmenuCurrent ); + break; + + case VK_SPACE: + case VK_RETURN: + fClosed = !MENU_ExecFocusedItem( hwnd, hmenuCurrent, + &hmenuCurrent ); + break; + + case VK_ESCAPE: + fClosed = TRUE; + break; + + default: + break; + } + break; /* WM_KEYDOWN */ + + case WM_SYSKEYDOWN: + switch(msg.wParam) + { + case VK_MENU: + fClosed = TRUE; + break; + + } + break; /* WM_SYSKEYDOWN */ + + case WM_CHAR: + { + /* Hack to avoid control chars. */ + /* We will find a better way real soon... */ + if ((msg.wParam <= 32) || (msg.wParam >= 127)) break; + pos = MENU_FindItemByKey( hwnd, hmenuCurrent, msg.wParam ); + if (pos == (WORD)-2) fClosed = TRUE; + else if (pos == (WORD)-1) MessageBeep(0); + else + { + MENU_SelectItem( hmenuCurrent, pos ); + fClosed = !MENU_ExecFocusedItem( hwnd, hmenuCurrent, + &hmenuCurrent ); + + } + } + break; /* WM_CHAR */ + } /* switch(msg.message) */ + } + else + { + DispatchMessage( &msg ); + } + if (fEndMenuCalled) fClosed = TRUE; + + if (!fClosed) /* Remove the message from the queue */ + PeekMessage( &msg, 0, 0, 0, PM_REMOVE ); + } + ReleaseCapture(); + MENU_HideSubPopups( hmenu ); + if (menu->wFlags & MF_POPUP) ShowWindow( menu->hWnd, SW_HIDE ); + MENU_SelectItem( hmenu, NO_SELECTED_ITEM ); + fEndMenuCalled = FALSE; + return TRUE; +} + + +/*********************************************************************** + * MENU_TrackMouseMenuBar + * + * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand(). + */ +void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt ) +{ + WND *wndPtr = WIN_FindWndPtr( hwnd ); + MENU_TrackMenu( (HMENU)wndPtr->wIDmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, + pt.x, pt.y, hwnd, NULL ); +} + + +/*********************************************************************** + * MENU_TrackKbdMenuBar + * + * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand(). + */ +void MENU_TrackKbdMenuBar( HWND hwnd, WORD wParam ) +{ + WND *wndPtr = WIN_FindWndPtr( hwnd ); + /* Select first selectable item */ + MENU_SelectItem( wndPtr->wIDmenu, NO_SELECTED_ITEM ); + MENU_SelectNextItem( (HMENU)wndPtr->wIDmenu ); + MENU_TrackMenu( (HMENU)wndPtr->wIDmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, + 0, 0, hwnd, NULL ); +} + + +/********************************************************************** + * TrackPopupMenu [USER.416] + */ +BOOL TrackPopupMenu( HMENU hMenu, WORD wFlags, short x, short y, + short nReserved, HWND hWnd, LPRECT lpRect ) +{ + if (!MENU_ShowPopup( hWnd, hMenu, 0, x, y )) return FALSE; + return MENU_TrackMenu( hMenu, wFlags, 0, 0, hWnd, lpRect ); +} + + +/*********************************************************************** + * PopupMenuWndProc + */ +LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam ) +{ + switch(message) + { + case WM_CREATE: + { #ifdef DEBUG_MENU - printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop); + printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam); #endif - if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop); - if (suppress_draw) return; - - FillRect(hDC, lprect, sysColorObjects.hbrushMenu ); - SelectObject( hDC, sysColorObjects.hpenWindowFrame ); - MoveTo( hDC, lprect->left, lprect->bottom ); - LineTo( hDC, lprect->right, lprect->bottom ); - - if (lppop->nItems == 0) return; - for (lpitem = lppop->firstItem; lpitem != NULL; lpitem = lpitem->next ) - { - MENU_DrawMenuItem( hDC, lpitem, lprect, TRUE ); + CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam; + HMENU hmenu = (HMENU) ((int)createStruct->lpCreateParams & 0xffff); + SetWindowWord( hwnd, 0, hmenu ); + return 0; } -} + case WM_MOUSEACTIVATE: /* We don't want to be activated */ + return MA_NOACTIVATE; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint( hwnd, &ps ); + MENU_DrawPopupMenu( hwnd, ps.hdc, + (HMENU)GetWindowWord( hwnd, 0 ) ); + EndPaint( hwnd, &ps ); + return 0; + } -LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet) -{ - LPMENUITEM lpitem; - UINT i; - if (lpRet != NULL) *lpRet = 0; - if (lppop == NULL) return NULL; - if (lppop->nItems == 0) return NULL; - lpitem = lppop->firstItem; - for(i = 0; i < lppop->nItems; i++) { - if (lpitem == NULL) return NULL; -#ifdef DEBUG_MENUFINDITEM - printf("FindItem // left=%d top=%d right=%d bottom=%d\n", - lpitem->rect.left, lpitem->rect.top, - lpitem->rect.right, lpitem->rect.bottom); -#endif - if (x > lpitem->rect.left && x < lpitem->rect.right && - y > lpitem->rect.top && y < lpitem->rect.bottom) { - if (lpRet != NULL) *lpRet = i; - return lpitem; - } - lpitem = (LPMENUITEM)lpitem->next; - } - return NULL; + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } + return 0; } -LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet) -{ - LPMENUITEM lpitem; - UINT i; - if (lppop == NULL) return NULL; - - if (lppop->nItems == 0) return NULL; - lpitem = lppop->firstItem; - for(i = 0; i < lppop->nItems; i++) { - if (lpitem == NULL) return NULL; -#ifdef DEBUG_MENUFINDITEM - printf("FindItemBySelKey // key=%04X lpitem->sel_key=%04X\n", - key, lpitem->sel_key); -#endif - if (key == lpitem->sel_key) { - if (lpRet != NULL) *lpRet = i; - return lpitem; - } - lpitem = (LPMENUITEM)lpitem->next; - } - return NULL; -} - - - - - - /*********************************************************************** * MENU_GetMenuBarHeight * @@ -1090,60 +1384,18 @@ WORD MENU_GetMenuBarHeight( HWND hwnd, WORD menubarWidth, int orgX, int orgY ) WND *wndPtr; LPPOPUPMENU lppop; - if (!(lppop = PopupMenuGetWindowAndStorage( hwnd, &wndPtr ))) return 0; - if (!wndPtr) return 0; + if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0; + if (!(lppop = (LPPOPUPMENU)USER_HEAP_ADDR( wndPtr->wIDmenu ))) return 0; hdc = GetDC( hwnd ); SetRect( &rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU ); MENU_MenuBarCalcSize( hdc, &rectBar, lppop ); ReleaseDC( hwnd, hdc ); - printf( "MENU_GetMenuBarHeight: returning %d\n", lppop->Height ); return lppop->Height; } -/*********************************************************************** - * FindMenuItem - */ -LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags) -{ - LPPOPUPMENU menu; - LPMENUITEM lpitem; - int i; - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) { - GlobalUnlock(hMenu); - return FALSE; - } - lpitem = menu->firstItem; - if (wFlags & MF_BYPOSITION) { - for (i = 0; i < nPos; i++, lpitem = lpitem->next) - if (lpitem == NULL) return NULL; - } - else { - for (i = 0; i < menu->nItems && lpitem != NULL; i++) { - if (lpitem->item_id == nPos) return lpitem; - lpitem = lpitem->next; - } - return NULL; - } - return lpitem; -} -LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos) -{ - LPMENUITEM lpitem; - int i; - if (menu == NULL) return NULL; - lpitem = menu->firstItem; - for (i = 0; i < menu->nItems; i++) { - if (lpitem == NULL) return NULL; - if (i == nPos) return(lpitem); - lpitem = (LPMENUITEM)lpitem->next; - } - return NULL; -} - WORD GetSelectionKey(LPSTR str) { @@ -1206,35 +1458,6 @@ int GetShortCutPos(LPSTR str) } - -BOOL HideAllSubPopupMenu(LPPOPUPMENU menu) -{ - LPPOPUPMENU submenu; - LPMENUITEM lpitem; - BOOL someClosed = FALSE; - int i; - if (menu == NULL) return; - lpitem = menu->firstItem; - for (i = 0; i < menu->nItems; i++) { - if (lpitem == NULL) return; - if (lpitem->item_flags & MF_POPUP) { - submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id); - if (submenu != NULL) { - if (IsWindowVisible(submenu->hWnd)) { - ShowWindow(submenu->hWnd, SW_HIDE); - someClosed = TRUE; - } - GlobalUnlock((HMENU)lpitem->item_id); - } - } - lpitem = (LPMENUITEM)lpitem->next; - } - return someClosed; -} - - - - /********************************************************************** * ChangeMenu [USER.153] */ @@ -1264,18 +1487,10 @@ BOOL CheckMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags) #ifdef DEBUG_MENU printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags); #endif - lpitem = FindMenuItem(hMenu, wItemID, wFlags); - if (lpitem != NULL) { - if ((wFlags & MF_CHECKED) == MF_CHECKED) - lpitem->item_flags |= MF_CHECKED; - else - lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED); -#ifdef DEBUG_MENU - printf("CheckMenuItem // Found !\n"); -#endif - return(TRUE); - } - return FALSE; + if (!(lpitem = MENU_FindItem(&hMenu, &wItemID, wFlags))) return FALSE; + if (wFlags & MF_CHECKED) lpitem->item_flags |= MF_CHECKED; + else lpitem->item_flags &= ~MF_CHECKED; + return TRUE; } @@ -1288,7 +1503,7 @@ BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags) #ifdef DEBUG_MENU printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags); #endif - if (!(lpitem = FindMenuItem(hMenu, wItemID, wFlags))) return FALSE; + if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return FALSE; /* We can't have MF_GRAYED and MF_DISABLED together */ if (wFlags & MF_GRAYED) @@ -1311,7 +1526,7 @@ BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags) * GetMenuString [USER.161] */ int GetMenuString(HMENU hMenu, WORD wItemID, - LPSTR str, short nMaxSiz, WORD wFlags) + LPSTR str, short nMaxSiz, WORD wFlags) { LPMENUITEM lpitem; int maxsiz; @@ -1320,7 +1535,7 @@ int GetMenuString(HMENU hMenu, WORD wItemID, hMenu, wItemID, str, nMaxSiz, wFlags); #endif if (str == NULL) return FALSE; - lpitem = FindMenuItem(hMenu, wItemID, wFlags); + lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags ); if (lpitem != NULL) { if (lpitem->item_text != NULL) { maxsiz = min(nMaxSiz - 1, strlen(lpitem->item_text)); @@ -1342,17 +1557,18 @@ int GetMenuString(HMENU hMenu, WORD wItemID, */ BOOL HiliteMenuItem(HWND hWnd, HMENU hMenu, WORD wItemID, WORD wHilite) { - LPPOPUPMENU menu; - LPMENUITEM lpitem; + LPPOPUPMENU menu; + LPMENUITEM lpitem; #ifdef DEBUG_MENU printf("HiliteMenuItem(%04X, %04X, %04X, %04X);\n", hWnd, hMenu, wItemID, wHilite); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return FALSE; - lpitem = FindMenuItem(hMenu, wItemID, wHilite); - if (lpitem == NULL) return FALSE; - return FALSE; + if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wHilite ))) return FALSE; + if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE; + if (menu->FocusedItem == wItemID) return TRUE; + MENU_HideSubPopups( hMenu ); + MENU_SelectItem( hMenu, wItemID ); + return TRUE; } @@ -1361,16 +1577,18 @@ BOOL HiliteMenuItem(HWND hWnd, HMENU hMenu, WORD wItemID, WORD wHilite) */ WORD GetMenuState(HMENU hMenu, WORD wItemID, WORD wFlags) { - LPPOPUPMENU menu; - LPMENUITEM lpitem; + LPMENUITEM lpitem; #ifdef DEBUG_MENU - printf("GetMenuState(%04X, %04X, %04X);\n", hMenu, wItemID, wFlags); + printf("GetMenuState(%04X, %04X, %04X);\n", hMenu, wItemID, wFlags); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return -1; - lpitem = FindMenuItem(hMenu, wItemID, wFlags); - if (lpitem == NULL) return -1; - return lpitem->item_flags; + if (!(lpitem = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return -1; + if (lpitem->item_flags & MF_POPUP) + { + POPUPMENU *menu = (POPUPMENU *) USER_HEAP_ADDR( lpitem->item_id ); + if (!menu) return -1; + else return (menu->nItems << 8) | (menu->wFlags & 0xff); + } + else return lpitem->item_flags; } @@ -1383,7 +1601,7 @@ WORD GetMenuItemCount(HMENU hMenu) #ifdef DEBUG_MENU printf("GetMenuItemCount(%04X);\n", hMenu); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); + menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu); if (menu == NULL) return (WORD)-1; #ifdef DEBUG_MENU printf("GetMenuItemCount(%04X) return %d \n", hMenu, menu->nItems); @@ -1397,24 +1615,17 @@ WORD GetMenuItemCount(HMENU hMenu) */ WORD GetMenuItemID(HMENU hMenu, int nPos) { - WORD i; - LPPOPUPMENU menu; - LPMENUITEM lpitem; - printf("GetMenuItemID(%04X, %d);\n", hMenu, nPos); - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return -1; - lpitem = menu->firstItem; - for (i = 0; i < menu->nItems; i++) { - if (lpitem == NULL) break; - if (i == nPos) { + LPPOPUPMENU menu; + MENUITEM *item; + #ifdef DEBUG_MENU - printf("GetMenuItemID // Found !\n"); + printf("GetMenuItemID(%04X, %d);\n", hMenu, nPos); #endif - return lpitem->item_id; - } - lpitem = (LPMENUITEM)lpitem->next; - } - return -1; + if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return -1; + if ((nPos < 0) || (nPos >= menu->nItems)) return -1; + item = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + if (item[nPos].item_flags & MF_POPUP) return -1; + return item[nPos].item_id; } @@ -1423,64 +1634,70 @@ WORD GetMenuItemID(HMENU hMenu, int nPos) */ BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem) { - LPPOPUPMENU menu; - HANDLE hNewItem; - LPMENUITEM lpitem, lpitem2; + HANDLE hNewItems; + MENUITEM *lpitem, *newItems; + LPPOPUPMENU menu; + #ifdef DEBUG_MENU - if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0) + if (IS_STRING_ITEM(wFlags)) printf("InsertMenu (%04X, %04X, %04X, '%s') !\n", hMenu, wFlags, wItemID, lpNewItem); - else + else printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n", - hMenu, nPos, wFlags, wItemID, lpNewItem); + hMenu, nPos, wFlags, wItemID, lpNewItem); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return FALSE; - lpitem = FindMenuItem(hMenu, nPos, wFlags); - if (lpitem == NULL) lpitem = menu->firstItem; - hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM)); - if (hNewItem == 0) { - GlobalUnlock(hMenu); - return FALSE; - } - lpitem2 = (LPMENUITEM)GlobalLock(hNewItem); - if (lpitem2 == NULL) { - GlobalFree(hNewItem); - GlobalUnlock(hMenu); - return FALSE; - } - lpitem2->hItem = hNewItem; - lpitem2->item_flags = wFlags; - lpitem2->item_id = wItemID; - if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | - MF_MENUBREAK | MF_SEPARATOR))) { - lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1); - lpitem2->item_text = GlobalLock(lpitem2->hText); - if (lpitem2->item_text != NULL) - strcpy(lpitem2->item_text, lpNewItem); - else { - printf("InsertMenu // Bad Alloc !\n"); - return FALSE; - } - lpitem2->sel_key = GetSelectionKey(lpitem2->item_text); - } - else { - lpitem2->item_text = lpNewItem; - } - if (lpitem == NULL) { - menu->firstItem = lpitem2; - lpitem2->prev = NULL; - lpitem2->next = NULL; - } - else { - lpitem2->prev = lpitem; - lpitem2->next = lpitem->next; - if (lpitem2->next != NULL) lpitem2->next->prev = lpitem2; - lpitem->next = lpitem2; - } - menu->nItems++; - GlobalUnlock(hMenu); - return TRUE; + + /* Find where to insert new item */ + + if ((wFlags & MF_BYPOSITION) && (nPos == (WORD)-1)) + { + /* Special case: append to menu */ + if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE; + nPos = menu->nItems; + } + else + { + if (!MENU_FindItem( &hMenu, &nPos, wFlags )) return FALSE; + if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE; + } + + /* Create new items array */ + + hNewItems = USER_HEAP_ALLOC( GMEM_MOVEABLE, + sizeof(MENUITEM) * (menu->nItems+1) ); + if (!hNewItems) return FALSE; + newItems = (MENUITEM *) USER_HEAP_ADDR( hNewItems ); + if (menu->nItems > 0) + { + /* Copy the old array into the new */ + MENUITEM *oldItems = (MENUITEM *) USER_HEAP_ADDR( menu->hItems ); + if (nPos > 0) memcpy( newItems, oldItems, nPos * sizeof(MENUITEM) ); + if (nPos < menu->nItems) memcpy( &newItems[nPos+1], &oldItems[nPos], + (menu->nItems-nPos)*sizeof(MENUITEM) ); + + USER_HEAP_FREE( menu->hItems ); + } + menu->hItems = hNewItems; + menu->nItems++; + + /* Store the new item data */ + + lpitem = &newItems[nPos]; + lpitem->item_flags = wFlags & ~(MF_HILITE | MF_MOUSESELECT); + lpitem->item_id = wItemID; + + if (IS_STRING_ITEM(wFlags)) + { + lpitem->hText = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(lpNewItem)+1 ); + lpitem->item_text = (char *)USER_HEAP_ADDR( lpitem->hText ); + strcpy( lpitem->item_text, lpNewItem ); + lpitem->sel_key = GetSelectionKey( lpitem->item_text ); + } + else lpitem->item_text = lpNewItem; + SetRectEmpty( &lpitem->rect ); + lpitem->hCheckBit = hStdCheck; + lpitem->hUnCheckBit = 0; + return TRUE; } @@ -1489,65 +1706,7 @@ BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt */ BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem) { - LPPOPUPMENU menu; - HANDLE hNewItem; - LPMENUITEM lpitem, lpitem2; -#ifdef DEBUG_MENU - if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0) - printf("AppendMenu (%04X, %04X, %04X, '%s') !\n", - hMenu, wFlags, wItemID, lpNewItem); - else - printf("AppendMenu (%04X, %04X, %04X, %08X) !\n", - hMenu, wFlags, wItemID, lpNewItem); -#endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return FALSE; - lpitem = menu->firstItem; - if (lpitem != NULL) { - while (lpitem->next != NULL) { - lpitem = (LPMENUITEM)lpitem->next; - } - } - hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM)); - if (hNewItem == 0) { - GlobalUnlock(hMenu); - return FALSE; - } - lpitem2 = (LPMENUITEM)GlobalLock(hNewItem); - lpitem2->hItem = hNewItem; - if (lpitem2 == NULL) { - GlobalFree(hNewItem); - GlobalUnlock(hMenu); - return FALSE; - } - lpitem2->item_flags = wFlags; - lpitem2->item_id = wItemID; - if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | - MF_MENUBREAK | MF_SEPARATOR))) { - lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1); - lpitem2->item_text = GlobalLock(lpitem2->hText); - if (lpitem2->item_text != NULL) - strcpy(lpitem2->item_text, lpNewItem); - else { - printf("AppendMenu // Bad Alloc !\n"); - return FALSE; - } - lpitem2->sel_key = GetSelectionKey(lpitem2->item_text); - } - else { - lpitem2->item_text = lpNewItem; - } - if (lpitem == NULL) - menu->firstItem = lpitem2; - else - lpitem->next = lpitem2; - lpitem2->prev = lpitem; - lpitem2->next = NULL; - lpitem2->hCheckBit = (HBITMAP)NULL; - lpitem2->hUnCheckBit = (HBITMAP)NULL; - menu->nItems++; - GlobalUnlock(hMenu); - return TRUE; + return InsertMenu( hMenu, -1, wFlags | MF_BYPOSITION, wItemID, lpNewItem ); } @@ -1556,36 +1715,35 @@ BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem) */ BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags) { - LPPOPUPMENU menu; - LPMENUITEM lpitem; - int i; + LPPOPUPMENU menu; + LPMENUITEM lpitem; #ifdef DEBUG_MENU printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return FALSE; - lpitem = menu->firstItem; - for (i = 0; i < menu->nItems; i++) { - if (lpitem == NULL) break; - if (i == nPos) { - lpitem->prev->next = lpitem->next; - lpitem->next->prev = lpitem->prev; - if (!(lpitem->item_flags & - (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | - MF_MENUBREAK | MF_SEPARATOR))) { - GlobalUnlock(lpitem->hText); - GlobalFree(lpitem->hText); - } - GlobalFree(lpitem->hItem); - GlobalUnlock(hMenu); - return TRUE; - } - lpitem = (LPMENUITEM)lpitem->next; - printf("RemoveMenu // during loop items !\n"); - } - printf("RemoveMenu // after loop items !\n"); - GlobalUnlock(hMenu); - return FALSE; + if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE; + if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return FALSE; + + /* Remove item */ + + if (IS_STRING_ITEM(lpitem->item_flags)) USER_HEAP_FREE( lpitem->hText ); + if (--menu->nItems == 0) + { + USER_HEAP_FREE( menu->hItems ); + menu->hItems = 0; + } + else + { + while(nPos < menu->nItems) + { + *lpitem = *(lpitem+1); + lpitem++; + nPos++; + } + menu->hItems = USER_HEAP_REALLOC( menu->hItems, + menu->nItems * sizeof(MENUITEM), + GMEM_MOVEABLE ); + } + return TRUE; } @@ -1594,35 +1752,12 @@ BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags) */ BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags) { - LPPOPUPMENU menu; - LPMENUITEM lpitem; - int i; -#ifdef DEBUG_MENU - printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags); -#endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) { - GlobalUnlock(hMenu); - return FALSE; - } - lpitem = FindMenuItem(hMenu, nPos, wFlags); - if (lpitem != NULL) { - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) - DestroyMenu((HMENU)lpitem->item_id); - if (!(lpitem->item_flags & - (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | - MF_MENUBREAK | MF_SEPARATOR))) { - GlobalUnlock(lpitem->hText); - GlobalFree(lpitem->hText); - } - if (lpitem->prev) lpitem->prev->next = lpitem->next; - if (lpitem->next) lpitem->next->prev = lpitem->prev; - GlobalFree(lpitem->hItem); - GlobalUnlock(hMenu); - return TRUE; - } - GlobalUnlock(hMenu); - return FALSE; + MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags ); + if (!item) return FALSE; + if (item->item_flags & MF_POPUP) DestroyMenu( item->item_id ); + /* nPos is now the position of the item */ + RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION ); + return TRUE; } @@ -1631,48 +1766,31 @@ BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags) */ BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem) { - LPPOPUPMENU menu; - LPMENUITEM lpitem; - int i; + LPMENUITEM lpitem; #ifdef DEBUG_MENU - if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0) - printf("ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n", - hMenu, nPos, wFlags, wItemID, lpNewItem); - else - printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n", - hMenu, nPos, wFlags, wItemID, lpNewItem); + if (IS_STRING_ITEM(wFlags)) + printf("ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n", + hMenu, nPos, wFlags, wItemID, lpNewItem); + else + printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n", + hMenu, nPos, wFlags, wItemID, lpNewItem); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return FALSE; - lpitem = menu->firstItem; - for (i = 0; i < menu->nItems; i++) { - if (lpitem == NULL) break; - if (i == nPos) { - lpitem->item_flags = wFlags; - lpitem->item_id = wItemID; - if (!(lpitem->item_flags & - (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | - MF_MENUBREAK | MF_SEPARATOR))) { - GlobalUnlock(lpitem->hText); - GlobalFree(lpitem->hText); - lpitem->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1); - lpitem->item_text = GlobalLock(lpitem->hText); - printf("ModifyMenu %08X %08X '%s') !\n", - lpitem->item_text, lpNewItem, lpNewItem); - if (lpitem->item_text != NULL) - strcpy(lpitem->item_text, lpNewItem); - else - printf("ModifyMenu // Bad Alloc !\n"); - } - else - lpitem->item_text = lpNewItem; - GlobalUnlock(hMenu); - return(TRUE); - } - lpitem = (LPMENUITEM)lpitem->next; - } - GlobalUnlock(hMenu); - return FALSE; + if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE; + + if (IS_STRING_ITEM(lpitem->item_flags)) USER_HEAP_FREE( lpitem->hText ); + lpitem->item_flags = wFlags & ~(MF_HILITE | MF_MOUSESELECT); + lpitem->item_id = wItemID; + + if (IS_STRING_ITEM(wFlags)) + { + lpitem->hText = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(lpNewItem)+1 ); + lpitem->item_text = (char *)USER_HEAP_ADDR( lpitem->hText ); + strcpy( lpitem->item_text, lpNewItem ); + lpitem->sel_key = GetSelectionKey( lpitem->item_text ); + } + else lpitem->item_text = lpNewItem; + SetRectEmpty( &lpitem->rect ); + return TRUE; } @@ -1681,238 +1799,13 @@ BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewIt */ HMENU CreatePopupMenu() { - HANDLE hItem; - HMENU hMenu; - LPPOPUPMENU menu; -#ifdef DEBUG_MENU - printf("CreatePopupMenu !\n"); -#endif - hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU)); - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) { - GlobalFree(hMenu); - return 0; - } - menu->nItems = 0; - menu->firstItem = NULL; - menu->ownerWnd = 0; - menu->hWndPrev = 0; - menu->hWnd = 0; - menu->hWndParent = 0; - menu->MouseFlags = 0; - menu->BarFlag = FALSE; - menu->SysFlag = FALSE; - menu->ChildFlag = TRUE; - menu->Width = 100; - menu->Height = 0; - GlobalUnlock(hMenu); -#ifdef DEBUG_MENU - printf("CreatePopupMenu // return %04X\n", hMenu); -#endif - return hMenu; -} + HMENU hmenu; + POPUPMENU *menu; - -/********************************************************************** - * TrackPopupMenu [USER.416] - */ -BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y, - short nReserved, HWND hWnd, LPRECT lpRect) -{ - WND *wndPtr; - LPPOPUPMENU lppop; - RECT rect; -#ifdef DEBUG_MENU - printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n", - hMenu, wFlags, x, y, nReserved, hWnd, lpRect); -#endif - lppop = (LPPOPUPMENU) GlobalLock(hMenu); - if (lppop == NULL) { - printf("TrackPopupMenu // Bad menu handle %04X !\n", hMenu); - return FALSE; - } - wndPtr = WIN_FindWndPtr(hWnd); - if (wndPtr == NULL) { - printf("TrackPopupMenu // Bad window handle %04X !\n", hWnd); - return FALSE; - } - lppop->ownerWnd = hWnd; - lppop->hWndPrev = GetFocus(); - if (lppop->hWnd == (HWND)NULL) { - lppop->hWnd = CreateWindow(POPUPMENU_CLASS_NAME, "", - WS_POPUP | WS_BORDER, - x, y, lppop->Width, lppop->Height, (HWND)NULL, 0, - wndPtr->hInstance, (LPSTR)lppop); - if (lppop->hWnd == 0) { - printf("TrackPopupMenu // Can't create PopupMenu window !\n"); - return FALSE; - } - } - if (!lppop->BarFlag) { - MENU_PopupMenuCalcSize(lppop->hWnd); -#ifdef DEBUG_MENU - printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n", - x, y, lppop->Width, lppop->Height); -#endif - SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height + 2, - SWP_NOACTIVATE | SWP_NOZORDER); - } - ShowWindow(lppop->hWnd, SW_SHOWNOACTIVATE); - SetFocus(lppop->hWnd); - if (!MenuHasFocus) { -#ifdef DEBUG_MENU - printf("TrackPopupMenu // before MenuFocusLoop !\n"); -#endif - MenuFocusLoop(hWnd, NULL); -#ifdef DEBUG_MENU - printf("TrackPopupMenu // after MenuFocusLoop !\n"); -#endif - } - GlobalUnlock(hMenu); - return TRUE; -} - - -BOOL ActivateMenuBarFocus(HWND hWnd) -{ - WND *wndPtr; - LPPOPUPMENU lpmenu; - BOOL bRet; - MSG msg; - if (MenuHasFocus) return FALSE; - wndPtr = WIN_FindWndPtr(hWnd); - if (wndPtr == NULL) return FALSE; -#ifdef DEBUG_MENU - printf("ActivateMenuBarFocus (%04X) !\n", hWnd); -#endif - while((wndPtr->dwStyle & WS_CHILD) == WS_CHILD) { - hWnd = GetParent(hWnd); - printf("ActivateMenuBarFocus // next Parent=%04X !\n", hWnd); - wndPtr = WIN_FindWndPtr(hWnd); - if (wndPtr == NULL) return FALSE; - } - if ((wndPtr->dwStyle & WS_CHILD) == 0 && wndPtr->wIDmenu != 0) { - lpmenu = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu); - if (lpmenu == NULL) return FALSE; - lpmenu->hWndPrev = GetFocus(); - SetFocus(hWnd); - MenuItemSelect(hWnd, lpmenu, 0); - bRet = MenuFocusLoop(hWnd, lpmenu); - GlobalUnlock(wndPtr->wIDmenu); - return bRet; - } - return FALSE; -} - - -BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu) -{ - MSG msg; -#ifdef DEBUG_MENU - printf("Enter in Menu Focus Loop !\n"); -#endif - MenuHasFocus = TRUE; - while(TRUE) { - if (!MenuHasFocus) break; - if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break; - TranslateMessage(&msg); - if (hWnd == msg.hwnd && lpmenu != NULL) { - if ((msg.message == WM_SYSKEYDOWN && msg.wParam == VK_MENU) || - (msg.message == WM_CHAR && msg.wParam == VK_ESCAPE)) { - HideAllSubPopupMenu(lpmenu); - break; - } - ScreenToClient(hWnd, &msg.pt); - msg.pt.y += lpmenu->rect.bottom; - switch(msg.message) { - case WM_LBUTTONDOWN: - case WM_NCLBUTTONDOWN: - SetCapture(hWnd); - MenuButtonDown(hWnd, lpmenu, msg.pt.x, msg.pt.y); - break; - case WM_LBUTTONUP: - case WM_NCLBUTTONUP: - MenuButtonUp(hWnd, lpmenu, msg.pt.x, msg.pt.y); - ReleaseCapture(); - break; - case WM_MOUSEMOVE: - case WM_NCMOUSEMOVE: - MenuMouseMove(hWnd, lpmenu, msg.wParam, msg.pt.x, msg.pt.y); - break; - case WM_KEYDOWN: - case WM_KEYUP: - case WM_CHAR: - PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam); - default: - DispatchMessage(&msg); - } - } - else - DispatchMessage(&msg); - } -EndOfFocus: - MenuHasFocus = FALSE; - if (lpmenu != NULL) MenuItemSelect(hWnd, lpmenu, -1); -#ifdef DEBUG_MENU - printf("End of Menu Focus Loop !\n"); -#endif - return TRUE; -} - - -/********************************************************************** - * NC_TrackSysMenu [Internal] - */ -void NC_TrackSysMenu(HWND hWnd) -{ - RECT rect; - LPPOPUPMENU lpsys; - WND *wndPtr = WIN_FindWndPtr(hWnd); -#ifdef DEBUG_MENU - printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd); -#endif - if (!wndPtr) return; - lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu); -#ifdef DEBUG_MENU - printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu); -#endif - if (lpsys == NULL) return; -#ifdef DEBUG_MENU - printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu); -#endif - lpsys->BarFlag = FALSE; - lpsys->SysFlag = TRUE; - lpsys->ChildFlag = FALSE; - lpsys->hWndParent = hWnd; - if (!IsWindowVisible(lpsys->hWnd)) { - GetWindowRect(hWnd, &rect); -#ifdef DEBUG_MENU - printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd); -#endif - if (MenuHasFocus) { - TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, - rect.left, rect.top + SYSMETRICS_CYSIZE, - 0, hWnd, (LPRECT)NULL); - } - else { - MenuHasFocus = TRUE; - TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, - rect.left, rect.top + SYSMETRICS_CYSIZE, - 0, hWnd, (LPRECT)NULL); - MenuHasFocus = FALSE; -#ifdef DEBUG_MENU - printf("NC_TrackSysMenu // before MenuFocusLoop !\n"); -#endif - MenuFocusLoop(hWnd, NULL); -#ifdef DEBUG_MENU - printf("NC_TrackSysMenu // after MenuFocusLoop !\n"); -#endif - } - } - else { - ShowWindow(lpsys->hWnd, SW_HIDE); - } - GlobalUnlock(wndPtr->hSysMenu); + if (!(hmenu = CreateMenu())) return 0; + menu = (POPUPMENU *) USER_HEAP_ADDR( hmenu ); + menu->wFlags |= MF_POPUP; + return hmenu; } @@ -1921,7 +1814,6 @@ void NC_TrackSysMenu(HWND hWnd) */ DWORD GetMenuCheckMarkDimensions() { - InitStdBitmaps(); return MAKELONG( check_bitmap_width, check_bitmap_height ); } @@ -1932,28 +1824,27 @@ DWORD GetMenuCheckMarkDimensions() BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags, HBITMAP hNewCheck, HBITMAP hNewUnCheck) { - LPPOPUPMENU menu; - LPMENUITEM lpitem; - int i; + LPMENUITEM lpitem; #ifdef DEBUG_MENU - printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n", - hMenu, nPos, wFlags, hNewCheck, hNewUnCheck); + printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n", + hMenu, nPos, wFlags, hNewCheck, hNewUnCheck); #endif - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) return FALSE; - lpitem = menu->firstItem; - for (i = 0; i < menu->nItems; i++) { - if (lpitem == NULL) break; - if (i == nPos) { - lpitem->hCheckBit = hNewCheck; - lpitem->hUnCheckBit = hNewUnCheck; - GlobalUnlock(hMenu); - return TRUE; - } - lpitem = (LPMENUITEM)lpitem->next; - } - GlobalUnlock(hMenu); - return FALSE; + if (!(lpitem = MENU_FindItem( &hMenu, &nPos, wFlags ))) return FALSE; + + if (!hNewCheck && !hNewUnCheck) + { + /* If both are NULL, restore default bitmaps */ + lpitem->hCheckBit = hStdCheck; + lpitem->hUnCheckBit = 0; + lpitem->item_flags &= ~MF_USECHECKBITMAPS; + } + else /* Install new bitmaps */ + { + lpitem->hCheckBit = hNewCheck; + lpitem->hUnCheckBit = hNewUnCheck; + lpitem->item_flags |= MF_USECHECKBITMAPS; + } + return TRUE; } @@ -1962,35 +1853,28 @@ BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags, */ HMENU CreateMenu() { - HANDLE hItem; - HMENU hMenu; - LPPOPUPMENU menu; + HMENU hMenu; + LPPOPUPMENU menu; #ifdef DEBUG_MENU printf("CreateMenu !\n"); #endif - hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU)); - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) { - GlobalFree(hMenu); - return 0; - } - menu->nItems = 0; - menu->firstItem = NULL; - menu->hWndPrev = 0; - menu->ownerWnd = 0; - menu->hWnd = 0; - menu->hWndParent = 0; - menu->MouseFlags = 0; - menu->BarFlag = TRUE; - menu->SysFlag = FALSE; - menu->ChildFlag = TRUE; - menu->Width = 100; - menu->Height = 0; - GlobalUnlock(hMenu); + if (!(hMenu = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(POPUPMENU) ))) + return 0; + menu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu); + menu->hNext = 0; + menu->wFlags = 0; + menu->wMagic = MENU_MAGIC; + menu->hTaskQ = 0; + menu->Width = 0; + menu->Height = 0; + menu->nItems = 0; + menu->hWnd = 0; + menu->hItems = 0; + menu->FocusedItem = NO_SELECTED_ITEM; #ifdef DEBUG_MENU - printf("CreateMenu // return %04X\n", hMenu); + printf("CreateMenu // return %04X\n", hMenu); #endif - return hMenu; + return hMenu; } @@ -2000,26 +1884,26 @@ HMENU CreateMenu() BOOL DestroyMenu(HMENU hMenu) { LPPOPUPMENU lppop; - LPMENUITEM lpitem, lpitem2; #ifdef DEBUG_MENU printf("DestroyMenu (%04X) !\n", hMenu); #endif if (hMenu == 0) return FALSE; - lppop = (LPPOPUPMENU) GlobalLock(hMenu); + lppop = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu); if (lppop == NULL) return FALSE; if (lppop->hWnd) DestroyWindow (lppop->hWnd); - lpitem = lppop->firstItem; - while (lpitem != NULL) { -#ifdef DEBUG_MENU - printf("DestroyMenu (%04X) // during loop items !\n", hMenu); -#endif - if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) { - DestroyMenu((HMENU)lpitem->item_id); - } - lpitem = (LPMENUITEM)lpitem->next; - } - GlobalUnlock(hMenu); - GlobalFree(hMenu); + + if (lppop->hItems) + { + int i; + MENUITEM *item = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems ); + for (i = lppop->nItems; i > 0; i--, item++) + { + if (item->item_flags & MF_POPUP) + DestroyMenu( item->item_flags & MF_POPUP ); + } + USER_HEAP_FREE( lppop->hItems ); + } + USER_HEAP_FREE( hMenu ); #ifdef DEBUG_MENU printf("DestroyMenu (%04X) // End !\n", hMenu); #endif @@ -2048,6 +1932,7 @@ HMENU LoadMenu(HINSTANCE instance, char *menu_name) return 0; } hMenu = LoadMenuIndirect((LPSTR)menu_desc); + GlobalUnlock( hMenu_desc ); return hMenu; } @@ -2091,14 +1976,13 @@ HMENU GetMenu(HWND hWnd) return wndPtr->wIDmenu; } + /********************************************************************** * SetMenu [USER.158] */ BOOL SetMenu(HWND hWnd, HMENU hMenu) { - RECT rect; LPPOPUPMENU lpmenu; - WORD flags; WND * wndPtr = WIN_FindWndPtr(hWnd); if (wndPtr == NULL) { printf("SetMenu(%04X, %04X) // Bad window handle !\n", hWnd, hMenu); @@ -2111,15 +1995,14 @@ BOOL SetMenu(HWND hWnd, HMENU hMenu) wndPtr->wIDmenu = hMenu; if (hMenu != 0) { - lpmenu = (LPPOPUPMENU) GlobalLock(hMenu); + lpmenu = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu); if (lpmenu == NULL) { printf("SetMenu(%04X, %04X) // Bad menu handle !\n", hWnd, hMenu); return FALSE; } - lpmenu->ownerWnd = hWnd; + lpmenu->hWnd = hWnd; + lpmenu->wFlags &= ~MF_POPUP; /* Can't be a popup */ lpmenu->Height = 0; /* Make sure we recalculate the size */ - ResetHiliteFlags(lpmenu); - GlobalUnlock(hMenu); } SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); @@ -2133,31 +2016,16 @@ BOOL SetMenu(HWND hWnd, HMENU hMenu) */ HMENU GetSubMenu(HMENU hMenu, short nPos) { - HMENU hSubMenu; - LPPOPUPMENU lppop; - LPMENUITEM lpitem; - int i; + LPPOPUPMENU lppop; + LPMENUITEM lpitem; #ifdef DEBUG_MENU - printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos); + printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos); #endif - if (hMenu == 0) return 0; - lppop = (LPPOPUPMENU) GlobalLock(hMenu); - if (lppop == NULL) return 0; - lpitem = lppop->firstItem; - for (i = 0; i < lppop->nItems; i++) { - if (lpitem == NULL) break; - if (i == nPos) { -#ifdef DEBUG_MENU - printf(" found %04x\n", lpitem->item_id); -#endif - if (lpitem->item_flags & MF_POPUP) - return lpitem->item_id; - else - return 0; - } - lpitem = (LPMENUITEM)lpitem->next; - } - return 0; + if (!(lppop = (LPPOPUPMENU) USER_HEAP_ADDR(hMenu))) return 0; + if ((WORD)nPos >= lppop->nItems) return 0; + lpitem = (MENUITEM *) USER_HEAP_ADDR( lppop->hItems ); + if (!(lpitem[nPos].item_flags & MF_POPUP)) return 0; + return lpitem[nPos].item_id; } @@ -2177,17 +2045,36 @@ void DrawMenuBar(HWND hWnd) #ifdef DEBUG_MENU printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu); #endif - lppop = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu); + lppop = (LPPOPUPMENU) USER_HEAP_ADDR(wndPtr->wIDmenu); if (lppop == NULL) return; lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */ SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); - GlobalUnlock(wndPtr->wIDmenu); } } +/*********************************************************************** + * EndMenu (USER.187) + */ +void EndMenu(void) +{ + /* Note: this won't work when we have multiple tasks... */ + fEndMenuCalled = TRUE; +} + + +/*********************************************************************** + * LookupMenuHandle (USER.217) + */ +HMENU LookupMenuHandle( HMENU hmenu, INT id ) +{ + if (!MENU_FindItem( &hmenu, &id, MF_BYCOMMAND )) return 0; + else return hmenu; +} + + /********************************************************************** * LoadMenuIndirect [USER.220] */ @@ -2195,89 +2082,40 @@ HMENU LoadMenuIndirect(LPSTR menu_template) { HMENU hMenu; MENU_HEADER *menu_desc; - LPPOPUPMENU lppop; #ifdef DEBUG_MENU printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template); #endif hMenu = CreateMenu(); menu_desc = (MENU_HEADER *)menu_template; ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu); - lppop = (LPPOPUPMENU) GlobalLock(hMenu); - ResetHiliteFlags(lppop); - GlobalUnlock(hMenu); return hMenu; } -/********************************************************************** - * InitStdBitmaps (Internal) - */ -void InitStdBitmaps() -{ - BITMAP bm; - if (hStdCheck == (HBITMAP)NULL) - { - hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK); - GetObject( hStdCheck, sizeof(BITMAP), (LPSTR)&bm ); - check_bitmap_width = bm.bmWidth; - check_bitmap_height = bm.bmHeight; - } - if (hStdMnArrow == (HBITMAP)NULL) - { - hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW); - GetObject( hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm ); - arrow_bitmap_width = bm.bmWidth; - arrow_bitmap_height = bm.bmHeight; - } -} - - /********************************************************************** * CopySysMenu (Internal) */ HMENU CopySysMenu() { - HMENU hMenu; - LPPOPUPMENU menu; - LPPOPUPMENU sysmenu; + HMENU hMenu; + LPPOPUPMENU sysmenu, menu; + MENUITEM *item; + int i; + + sysmenu = (LPPOPUPMENU) USER_HEAP_ADDR(hSysMenu); + if (!(hMenu = CreatePopupMenu())) return 0; + menu = (POPUPMENU *) USER_HEAP_ADDR( hMenu ); + menu->wFlags |= MF_SYSMENU; + item = (MENUITEM *) USER_HEAP_ADDR( sysmenu->hItems ); + for (i = 0; i < sysmenu->nItems; i++, item++) + { + AppendMenu( hMenu, item->item_flags, item->item_id, item->item_text ); + } + #ifdef DEBUG_MENU - printf("CopySysMenu entry !\n"); + printf("CopySysMenu hMenu=%04X !\n", hMenu); #endif - if (hSysMenu == 0) { -/* hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1)); */ -/* hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/ - hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); - if (hSysMenu == 0) { - printf("SysMenu not found in system resources !\n"); - return (HMENU)NULL; - } -#ifdef DEBUG_MENU - else - printf("SysMenu loaded from system resources %04X !\n", hSysMenu); -#endif - } - hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU)); - menu = (LPPOPUPMENU) GlobalLock(hMenu); - sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu); - if (menu != NULL && sysmenu != NULL) { - sysmenu->BarFlag = FALSE; - sysmenu->SysFlag = TRUE; - memcpy(menu, sysmenu, sizeof(POPUPMENU)); - } - else { - printf("CopySysMenu // Bad SysMenu pointers !\n"); - if (menu != NULL) { - GlobalUnlock(hMenu); - GlobalFree(hMenu); - } - return (HMENU)NULL; - } - GlobalUnlock(hMenu); - GlobalUnlock(hSysMenu); -#ifdef DEBUG_MENU - printf("CopySysMenu hMenu=%04X !\n", hMenu); -#endif - return hMenu; + return hMenu; } @@ -2320,17 +2158,13 @@ WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu) return next_item; } + /********************************************************************** - * IsMenu(USER.358) + * IsMenu (USER.358) */ -BOOL IsMenu(HMENU hMenu) +BOOL IsMenu( HMENU hmenu ) { - LPPOPUPMENU menu; - - menu = (LPPOPUPMENU) GlobalLock(hMenu); - if (menu == NULL) - return FALSE; - - GlobalUnlock(hMenu); - return TRUE; + LPPOPUPMENU menu; + if (!(menu = (LPPOPUPMENU) USER_HEAP_ADDR( hmenu ))) return FALSE; + return (menu->wMagic == MENU_MAGIC); } diff --git a/controls/static.c b/controls/static.c index 0f8419532b6..409fd03253a 100644 --- a/controls/static.c +++ b/controls/static.c @@ -127,7 +127,6 @@ LONG StaticWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam) break; } - GlobalUnlock(hWnd); return lResult; } @@ -187,7 +186,6 @@ static LONG PaintTextfn(HWND hwnd) DrawText(hdc, text, textlen, &rc, wFormat); USER_HEAP_FREE(hText); - GlobalUnlock(hwnd); EndPaint(hwnd, &ps); } @@ -231,7 +229,6 @@ static LONG PaintRectfn(HWND hwnd) DeleteObject((HANDLE)hPen); DeleteObject((HANDLE)hBrush); - GlobalUnlock(hwnd); EndPaint(hwnd, &ps); } @@ -273,7 +270,6 @@ static LONG PaintFramefn(HWND hwnd) DeleteObject((HANDLE)hPen); DeleteObject((HANDLE)hBrush); - GlobalUnlock(hwnd); EndPaint(hwnd, &ps); } @@ -304,7 +300,6 @@ static LONG PaintIconfn(HWND hwnd) hIcon = LoadIcon(wndPtr->hInstance, textPtr); DrawIcon(hdc, rc.left, rc.top, hIcon); EndPaint(hwnd, &ps); - GlobalUnlock(hwnd); } diff --git a/if1632/relay.c b/if1632/relay.c index 070a58a2f6d..3122d8bd3f8 100644 --- a/if1632/relay.c +++ b/if1632/relay.c @@ -290,7 +290,7 @@ void winestat(){ used++; if (table[j].handler) implemented++; else - printf("%s.%d\n", + printf("%s.%d not implemented\n", dll_builtin_table[i].dll_name, j); }; @@ -301,10 +301,11 @@ void winestat(){ perc = implemented * 100.00 / used; else perc = 0.0; - printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc); + if (used) + printf("%s: %d of %d (%3.1f %%)\n", dll_builtin_table[i].dll_name, implemented, used, perc); }; perc = timplemented * 100.00 / tused; - printf("TOTAL: %d of %d implemented (%3.1f %%)\n",timplemented, tused, perc); + printf("TOTAL: %d of %d winapi functions implemented (%3.1f %%)\n",timplemented, tused, perc); } #endif /* WINESTAT */ #endif /* !WINELIB */ diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec index 682dec546cd..4380277a8f0 100644 --- a/if1632/toolhelp.spec +++ b/if1632/toolhelp.spec @@ -15,16 +15,16 @@ length 83 60 pascal ModuleNext(ptr) ModuleNext(1) 61 pascal ModuleFindName(ptr ptr) ModuleFindName(1 2) 62 pascal ModuleFindHandle(ptr word) ModuleFindHandle(1 2) -# 63 1 0caa TASKFIRST exported, shared data -# 64 1 0ced TASKNEXT exported, shared data -# 65 1 0d2e TASKFINDHANDLE exported, shared data +63 pascal16 TaskFirst(ptr) TaskFirst(1) +64 pascal16 TaskNext(ptr) TaskNext(1) +65 pascal16 TaskFindHandle(ptr word) TaskFindHandle(1 2) # 66 1 0f1c STACKTRACEFIRST exported, shared data # 67 1 0f67 STACKTRACECSIPFIRST exported, shared data # 68 1 0fca STACKTRACENEXT exported, shared data # 69 1 28b0 CLASSFIRST exported, shared data # 70 1 2925 CLASSNEXT exported, shared data # 71 1 11ce SYSTEMHEAPINFO exported, shared data -# 72 1 13f4 MEMMANINFO exported, shared data +72 pascal16 MemManInfo(ptr) MemManInfo(1) # 73 1 1b72 NOTIFYREGISTER exported, shared data # 74 1 1c29 NOTIFYUNREGISTER exported, shared data # 75 1 2060 INTERRUPTREGISTER exported, shared data diff --git a/if1632/user.spec b/if1632/user.spec index 88c5d9de110..371b3d76f05 100644 --- a/if1632/user.spec +++ b/if1632/user.spec @@ -190,7 +190,7 @@ length 540 185 pascal GrayString(word word ptr ptr word word word word word) GrayString(1 2 3 4 5 6 7 8 9) 186 pascal SwapMouseButton(word) SwapMouseButton(1) -#187 ENDMENU +187 pascal EndMenu() EndMenu() 188 pascal SetSysModalWindow(word) SetSysModalWindow(1) 189 pascal GetSysModalWindow() GetSysModalWindow() 190 pascal GetUpdateRect(word ptr word) GetUpdateRect(1 2 3) @@ -201,7 +201,8 @@ length 540 195 pascal DlgDirListComboBox(word ptr word word word) DlgDirListComboBox(1 2 3 4 5) 196 pascal TabbedTextOut(word s_word s_word ptr s_word s_word ptr s_word) TabbedTextOut(1 2 3 4 5 6 7 8) -#197 GETTABBEDTEXTEXTENT +197 pascal GETTABBEDTEXTEXTENT(word ptr word word ptr) + GetTabbedTextExtent(1 2 3 4 5) #198 CASCADECHILDWINDOWS #199 TILECHILDWINDOWS 200 pascal OpenComm(ptr word word) OpenComm(1 2 3) @@ -221,7 +222,7 @@ length 540 214 pascal EscapeCommFunction(word word) EscapeCommFunction(1 2) 215 pascal FlushComm(word word) FlushComm(1 2) #216 USERSEEUSERDO -#217 LOOKUPMENUHANDLE +217 pascal LookupMenuHandle(word s_word) LookupMenuHandle(1 2) 218 pascal DialogBoxIndirect(word word word ptr) DialogBoxIndirect(1 2 3 4) 219 pascal CreateDialogIndirect(word ptr word ptr) CreateDialogIndirect(1 2 3 4) diff --git a/include/bitmaps/check_bitmap b/include/bitmaps/check_bitmap deleted file mode 100644 index bc76d9ffd3a..00000000000 --- a/include/bitmaps/check_bitmap +++ /dev/null @@ -1,7 +0,0 @@ -#define check_bitmap_width 10 -#define check_bitmap_height 10 -#define check_bitmap_x_hot 0 -#define check_bitmap_y_hot 0 -static char check_bitmap_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, - 0x63, 0x00, 0x36, 0x00, 0x1c, 0x00, 0x08, 0x00}; diff --git a/include/bitmaps/check_mark b/include/bitmaps/check_mark new file mode 100644 index 00000000000..4c7adcee16a --- /dev/null +++ b/include/bitmaps/check_mark @@ -0,0 +1,6 @@ +#define check_mark_width 14 +#define check_mark_height 14 +static char check_mark_bits[] = { + 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06, + 0x30, 0x02, 0x60, 0x03, 0x40, 0x01, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; diff --git a/include/bitmaps/menu_arrow b/include/bitmaps/menu_arrow new file mode 100644 index 00000000000..a38ff70478f --- /dev/null +++ b/include/bitmaps/menu_arrow @@ -0,0 +1,4 @@ +#define menu_arrow_width 7 +#define menu_arrow_height 11 +static char menu_arrow_bits[] = { + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00}; diff --git a/include/bitmaps/nocheck_bitmap b/include/bitmaps/nocheck_bitmap deleted file mode 100644 index a56ae3510ff..00000000000 --- a/include/bitmaps/nocheck_bitmap +++ /dev/null @@ -1,7 +0,0 @@ -#define nocheck_bitmap_width 10 -#define nocheck_bitmap_height 10 -#define nocheck_bitmap_x_hot 0 -#define nocheck_bitmap_y_hot 0 -static char nocheck_bitmap_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/include/dialog.h b/include/dialog.h index b6fe1b31942..3b333475656 100644 --- a/include/dialog.h +++ b/include/dialog.h @@ -25,6 +25,7 @@ typedef struct WORD xBaseUnit; WORD yBaseUnit; WORD fEnd; + HANDLE hDialogHeap; } DIALOGINFO; diff --git a/include/menu.h b/include/menu.h index c8776188cfd..2e0f7ca1d8c 100644 --- a/include/menu.h +++ b/include/menu.h @@ -6,42 +6,34 @@ #ifndef MENU_H #define MENU_H +#define MENU_MAGIC 0x554d /* 'MU' */ typedef struct tagMENUITEM { - struct tagMENUITEM *next; - struct tagMENUITEM *prev; - HANDLE hItem; WORD item_flags; WORD item_id; - WORD sel_key; - char *item_text; - HANDLE hText; RECT rect; + WORD sel_key; HBITMAP hCheckBit; HBITMAP hUnCheckBit; + char *item_text; + HANDLE hText; } MENUITEM, *LPMENUITEM; typedef struct tagPOPUPMENU { - HWND hWnd; /* PopupMenu window handle */ - HWND hWndParent; /* Parent PopupMenu window handle */ - HWND ownerWnd; /* Owner window */ - HWND hWndPrev; /* Previous Window Focus Owner */ - WORD nItems; /* Number of items on menu */ - MENUITEM *firstItem; - WORD FocusedItem; - WORD MouseFlags; - BOOL BarFlag; /* TRUE if menu is a MENUBAR */ - BOOL SysFlag; /* TRUE if menu is a SYSMENU */ - BOOL ChildFlag; /* TRUE if child of other menu */ - WORD Width; - WORD Height; - WORD CheckWidth; - WORD PopWidth; - RECT rect; + HMENU hNext; /* Next menu (compatibility only, always 0) */ + WORD wFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */ + WORD wMagic; /* Magic number */ + HANDLE hTaskQ; /* Task queue for this menu */ + WORD Width; /* Width of the whole menu */ + WORD Height; /* Height of the whole menu */ + WORD nItems; /* Number of items in the menu */ + HWND hWnd; /* Window containing the menu */ + HANDLE hItems; /* Handle to the items array */ + WORD FocusedItem; /* Currently focused item */ } POPUPMENU, *LPPOPUPMENU; typedef struct @@ -63,11 +55,4 @@ typedef struct char item_text[1]; /* Text for menu item */ } MENUITEMTEMPLATE; -void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop, - BOOL suppress_draw); -BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y); -void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y); -void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y); -extern void NC_TrackSysMenu(HWND hwnd); - #endif /* MENU_H */ diff --git a/include/message.h b/include/message.h index 5e6e9e867ca..66d792686c4 100644 --- a/include/message.h +++ b/include/message.h @@ -53,7 +53,7 @@ extern BOOL MSG_CreateSysMsgQueue( int size ); extern void hardware_event( WORD message, WORD wParam, LONG lParam, int xPos, int yPos, DWORD time, DWORD extraInfo ); extern BOOL MSG_GetHardwareMessage( LPMSG msg ); -extern BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, - short code, BOOL sendIdle ); +extern BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, HWND hwndOwner, + short code, WORD flags, BOOL sendIdle ); #endif /* MESSAGE_H */ diff --git a/include/msdos.h b/include/msdos.h index 99eccefdbde..e5443f10f22 100644 --- a/include/msdos.h +++ b/include/msdos.h @@ -17,29 +17,6 @@ struct dosdirent { #define DOSVERSION 0x0330; #define MAX_DOS_DRIVES 26 -#define EAX context->sc_eax -#define EBX context->sc_ebx -#define ECX context->sc_ecx -#define EDX context->sc_edx - -#define AX (context->sc_eax & 0x0000ffffL) -#define BX (context->sc_ebx & 0x0000ffffL) -#define CX (context->sc_ecx & 0x0000ffffL) -#define DX (context->sc_edx & 0x0000ffffL) - -#define CS context->sc_cs -#define DS context->sc_ds -#define ES context->sc_es -#define SS context->sc_ss - -#define DI context->sc_edi -#define SI context->sc_esi -#define SP context->sc_esp -#define EFL context->sc_efl - -#define SetCflag (EFL |= 0x00000001L) -#define ResetCflag (EFL &= 0xfffffffeL) - #define pointer(a,b) (BYTE*)(((WORD) a << 16) | b) #define segment(a) ((DWORD)a >> 16) #define offset(a) ((DWORD)a & 0xffff) diff --git a/include/registers.h b/include/registers.h new file mode 100644 index 00000000000..0284abf816e --- /dev/null +++ b/include/registers.h @@ -0,0 +1,50 @@ +#ifndef __WINE_REGISTERS_H +#define __WINE_REGISTERS_H + +#include +#include "autoconf.h" + +#ifndef PROCEMU + +#define EAX context->sc_eax +#define EBX context->sc_ebx +#define ECX context->sc_ecx +#define EDX context->sc_edx + +#define AX *(WORD*)&context->sc_eax +#define BX *(WORD*)&context->sc_ebx +#define CX *(WORD*)&context->sc_ecx +#define DX *(WORD*)&context->sc_edx + +#define AL *(BYTE*)&context->sc_eax +#define AH *(((BYTE*)&context->sc_eax)+1) +#define BL *(BYTE*)&context->sc_ebx +#define BH *(((BYTE*)&context->sc_ebx)+1) +#define CL *(BYTE*)&context->sc_ecx +#define CH *(((BYTE*)&context->sc_ecx)+1) +#define DL *(BYTE*)&context->sc_edx +#define DH *(((BYTE*)&context->sc_edx)+1) + +#define CS context->sc_cs +#define DS context->sc_ds +#define ES context->sc_es +#define SS context->sc_ss + +#define DI context->sc_edi +#define SI context->sc_esi +#define SP context->sc_esp +#define EFL context->sc_efl +#define EIP context->sc_eip + +#define SetCflag (EFL |= 0x00000001) +#define ResetCflag (EFL &= 0xfffffffe) + +#else + +#include "bx_bochs.h" + +#define SetCflag bx_STC() +#define ResetCflag bx_CLC() + +#endif /* PROCEMU */ +#endif /* __WINE_REGISTERS_H */ diff --git a/include/task.h b/include/task.h index 1c052657cf4..8be9787fbaf 100644 --- a/include/task.h +++ b/include/task.h @@ -7,30 +7,9 @@ #include "toolhelp.h" -typedef HANDLE HGLOBAL; - -typedef struct { - DWORD dwSize; - HTASK hTask; - HTASK hTaskParent; - HINSTANCE hInst; - HMODULE hModule; - WORD wSS; - WORD wSP; - WORD wStackTop; - WORD wStackMinimum; - WORD wStackBottom; - WORD wcEvents; - HGLOBAL hQueue; - char szModule[MAX_MODULE_NAME + 1]; - WORD wPSPOffset; - HANDLE hNext; -} TASKENTRY; -typedef TASKENTRY *LPTASKENTRY; - typedef struct { TASKENTRY te; - int unix_pid; + int unix_pid; HICON hIcon; HWND *lpWndList; void *lpPrevTask; diff --git a/include/toolhelp.h b/include/toolhelp.h index 6941d1b691e..40d7d9be5b5 100644 --- a/include/toolhelp.h +++ b/include/toolhelp.h @@ -4,9 +4,14 @@ #include "windows.h" DECLARE_HANDLE(HMODULE); +DECLARE_HANDLE(HGLOBAL); -#define MAX_MODULE_NAME 9 -#define MAX_PATH 255 +#define MAX_DATA 11 +#define MAX_MODULE_NAME 9 +#define MAX_PATH 255 +#define MAX_CLASSNAME 255 + +/* modules */ typedef struct { DWORD dwSize; @@ -23,4 +28,61 @@ BOOL ModuleNext(MODULEENTRY *lpModule); HMODULE ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName); HMODULE ModuleFindHandle(MODULEENTRY *lpModule, HMODULE hModule); +/* tasks */ + +typedef struct tagTASKENTRY { + DWORD dwSize; + HTASK hTask; + HTASK hTaskParent; + HINSTANCE hInst; + HMODULE hModule; + WORD wSS; + WORD wSP; + WORD wStackTop; + WORD wStackMinimum; + WORD wStackBottom; + WORD wcEvents; + HGLOBAL hQueue; + char szModule[MAX_MODULE_NAME + 1]; + WORD wPSPOffset; + HANDLE hNext; +} TASKENTRY; +typedef TASKENTRY *LPTASKENTRY; + +BOOL TaskFirst(LPTASKENTRY lpTask); +BOOL TaskNext(LPTASKENTRY lpTask); +BOOL TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask); +DWORD TaskSetCSIP(HTASK hTask, WORD wCS, WORD wIP); +DWORD TaskGetCSIP(HTASK hTask); +BOOL TaskSwitch(HTASK hTask, DWORD dwNewCSIP); + +/* mem info */ + +typedef struct tagMEMMANINFO { + DWORD dwSize; + DWORD dwLargestFreeBlock; + DWORD dwMaxPagesAvailable; + DWORD dwMaxPagesLockable; + DWORD dwTotalLinearSpace; + DWORD dwTotalUnlockedPages; + DWORD dwFreePages; + DWORD dwTotalPages; + DWORD dwFreeLinearSpace; + DWORD dwSwapFilePages; + WORD wPageSize; +} MEMMANINFO; +typedef MEMMANINFO *LPMEMMANINFO; + +typedef struct tagSYSHEAPINFO { + DWORD dwSize; + WORD wUserFreePercent; + WORD wGDIFreePercent; + HGLOBAL hUserSegment; + HGLOBAL hGDISegment; +} SYSHEAPINFO; +typedef SYSHEAPINFO *LPSYSHEAPINFO; + +BOOL MemManInfo(LPMEMMANINFO lpEnhMode); +BOOL SystemHeapInfo(LPSYSHEAPINFO lpSysHeap); + #endif /* __TOOLHELP_H */ diff --git a/include/windows.h b/include/windows.h index 3f14d8b3903..711210a5ee5 100644 --- a/include/windows.h +++ b/include/windows.h @@ -1496,6 +1496,8 @@ enum { WM_NULL, WM_CREATE, WM_DESTROY, WM_MOVE, WM_UNUSED0, WM_SIZE, WM_ACTIVATE #define WM_HSCROLL 0x0114 #define WM_VSCROLL 0x0115 +#define WM_ENTERIDLE 0x0121 + /* Mouse messages */ #define WM_MOUSEMOVE 0x0200 #define WM_LBUTTONDOWN 0x0201 @@ -2714,6 +2716,7 @@ Fb(HPALETTE,GDISelectPalette,HDC,a,HPALETTE,b) Fb(HMENU,GetSubMenu,HMENU,a,short,b) Fb(HMENU,GetSystemMenu,HWND,a,BOOL,b) Fb(HMENU,LoadMenu,HANDLE,a,LPSTR,b) +Fb(HMENU,LookupMenuHandle,HMENU,a,INT,b) Fb(HWND,ChildWindowFromPoint,HWND,a,POINT,b) Fb(HWND,FindWindow,LPSTR,a,LPSTR,b) Fb(HWND,GetDlgItem,HWND,a,WORD,b) diff --git a/loader/ldtlib.c b/loader/ldtlib.c index 40929d654db..181c4b12708 100644 --- a/loader/ldtlib.c +++ b/loader/ldtlib.c @@ -5,6 +5,8 @@ static char Copyright[] = "Copyright Robert J. Amstadt, 1993"; #include #include #include +#include "autoconf.h" + #ifdef linux #include #include diff --git a/loader/resource.c b/loader/resource.c index 662fa34ce6e..b69c5f2acbb 100644 --- a/loader/resource.c +++ b/loader/resource.c @@ -37,6 +37,8 @@ static struct w_files *ResourceFileInfo = NULL; static RESOURCE *Top = NULL; extern HINSTANCE hSysRes; +extern HBITMAP BITMAP_LoadOEMBitmap( WORD id ); /* objects/bitmap.c */ + HANDLE RSC_LoadResource(int instance, char *rsc_name, int type, int *image_size_ret); void RSC_LoadNameTable(void); @@ -1153,8 +1155,14 @@ LoadBitmap(HANDLE instance, LPSTR bmp_name) printf("LoadBitmap: instance = %04x, name = %08x\n", instance, bmp_name); #endif - if (instance == (HANDLE)NULL) instance = hSysRes; - if (!(hdc = GetDC(GetDesktopWindow()))) return 0; + if (!instance) + { + /* Try to create an OEM bitmap */ + hbitmap = BITMAP_LoadOEMBitmap( ((int)bmp_name) & 0xffff ); + if (hbitmap) return hbitmap; + /* Failed -> load it from sysres.dll */ + instance = hSysRes; + } rsc_mem = RSC_LoadResource(instance, bmp_name, NE_RSCTYPE_BITMAP, &image_size); @@ -1163,6 +1171,7 @@ LoadBitmap(HANDLE instance, LPSTR bmp_name) return 0; } lp = (long *) GlobalLinearLock(rsc_mem); + if (!(hdc = GetDC(0))) lp = NULL; if (lp == NULL) { GlobalFree(rsc_mem); diff --git a/loader/task.c b/loader/task.c index 569c64bff6b..d2276400ff1 100644 --- a/loader/task.c +++ b/loader/task.c @@ -10,6 +10,8 @@ static char Copyright[] = "Copyright Martin Ayotte, 1994"; #include #include #include +#include +#include #include "windows.h" #include "wine.h" #include "task.h" @@ -17,7 +19,6 @@ static char Copyright[] = "Copyright Martin Ayotte, 1994"; static LPWINETASKENTRY lpTaskList = NULL; static int nTaskCount = 0; - /********************************************************************** * GetCurrentTask [KERNEL.36] */ @@ -122,9 +123,14 @@ BOOL EnumTaskWindows(HANDLE hTask, FARPROC lpEnumFunc, LONG lParam) */ HANDLE CreateNewTask(HINSTANCE hInst, HTASK hTaskParent) { - HANDLE hTask; + HANDLE hTask; LPWINETASKENTRY lpTask = lpTaskList; LPWINETASKENTRY lpNewTask; + MODULEENTRY module; + + module.dwSize = sizeof(module); + ModuleFindHandle(&module, hInst); + if (lpTask != NULL) { while (TRUE) { if (lpTask->lpNextTask == NULL) break; @@ -160,7 +166,7 @@ HANDLE CreateNewTask(HINSTANCE hInst, HTASK hTaskParent) lpNewTask->te.wStackBottom = 0; lpNewTask->te.wcEvents = 0; lpNewTask->te.hQueue = 0; - sprintf(lpNewTask->te.szModule, "TASK%04X", hInst); + strcpy(lpNewTask->te.szModule, module.szModule); lpNewTask->te.wPSPOffset = 0; lpNewTask->unix_pid = getpid(); lpNewTask->lpWndList = (HWND *) malloc(MAXWIN_PER_TASK * sizeof(HWND)); @@ -245,4 +251,55 @@ BOOL RemoveWindowFromTask(HTASK hTask, HWND hWnd) return TRUE; } +BOOL TaskFirst(LPTASKENTRY lpTask) +{ + printf("TaskFirst(%8x)\n", (int) lpTask); + if (lpTaskList) { + memcpy(lpTask, &lpTaskList->te, lpTask->dwSize); + return TRUE; + } else + return FALSE; +} + +BOOL TaskNext(LPTASKENTRY lpTask) +{ + LPWINETASKENTRY list; + + printf("TaskNext(%8x)\n", (int) lpTask); + + list = lpTaskList; + while (list) { + if (list->te.hTask == lpTask->hTask) { + list = list->lpNextTask; + if (list) { + memcpy(lpTask, &list->te, lpTask->dwSize); + return TRUE; + } else + return FALSE; + } + list = list->lpNextTask; + } + return FALSE; +} + +BOOL TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask) +{ + static LPWINETASKENTRY list; + + printf("TaskFindHandle(%8x,%4x)\n", (int) lpTask, hTask); + + list = lpTaskList; + while (list) { + if (list->te.hTask == hTask) { + list = list->lpNextTask; + if (list) { + memcpy(lpTask, &list->te, lpTask->dwSize); + return TRUE; + } else + return FALSE; + } + list = list->lpNextTask; + } + return FALSE; +} diff --git a/memory/global.c b/memory/global.c index 75098684dab..117c5328277 100644 --- a/memory/global.c +++ b/memory/global.c @@ -8,6 +8,7 @@ static char Copyright[] = "Copyright Robert J. Amstadt, 1993"; #include #include #include "prototypes.h" +#include "toolhelp.h" #include "heap.h" #include "segmem.h" @@ -807,3 +808,11 @@ DWORD GetFreeSpace(UINT wFlags) printf("GetFreeSpace // return %ld !\n", total_free << 16); return total_free << 16; } + +/********************************************************************** + * MemManInfo (toolhelp.72) + */ +BOOL MemManInfo(LPMEMMANINFO lpmmi) +{ + return 1; +} diff --git a/misc/file.c b/misc/file.c index 92359fd6487..db2293dfe0d 100644 --- a/misc/file.c +++ b/misc/file.c @@ -23,13 +23,28 @@ #include #include #include +#include #include "prototypes.h" +#include "regfunc.h" +#include "windows.h" +#include "wine.h" +#include "msdos.h" +#include "registers.h" +#include "options.h" + +#define MAX_PATH 255 /* #define DEBUG_FILE /* */ char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256]; extern char WindowsPath[256]; +extern char WindowsPath[]; +extern WORD ExtendedError; + + +char *GetDosFileName(char *unixfilename); + /*************************************************************************** _lopen @@ -116,83 +131,153 @@ INT _lclose (INT hFile) /************************************************************************** OpenFile - - Warning: This is nearly totally untested. It compiles, that's it... - -SL 9/13/93 **************************************************************************/ INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle) { - int base, flags; - int handle; - char buf[256]; - -#ifdef DEBUG_FILE - fprintf(stderr,"OpenFile(%s,,%04X)\n",lpFileName,wStyle); -#endif - - base = wStyle & 0xF; - flags = wStyle & 0xFFF0; + int handle; + struct sigcontext_struct ccontext; + /* To make macros like EAX happy */ + struct sigcontext_struct *context=&ccontext; + char filename[MAX_PATH+1]; + int action; + struct stat s; + struct tm *now; + int res; + int verify_time; - flags &= 0xFF0F; /* strip SHARE bits for now */ - flags &= 0xD7FF; /* strip PROMPT & CANCEL bits for now */ - flags &= 0x7FFF; /* strip REOPEN bit for now */ - flags &= 0xFBFF; /* strib VERIFY bit for now */ + #ifdef DEBUG_FILE + fprintf(stderr,"Openfile(%s,,%d) ",lpFileName,wStyle); + #endif - if (flags & OF_CREATE) - { - base |= O_CREAT; - flags &= 0xEFFF; - } + action = wStyle & 0xff00; + + + /* OF_CREATE is completly different from all other options, so + handle it first */ -#ifdef DEBUG_FILE - fprintf(stderr,"now %d,%d\n",base,flags); -#endif + if (action & OF_CREATE) + { + int handle; + char *unixfilename; - if (flags & OF_EXIST) - { - printf("OpenFile // OF_EXIST '%s' !\n", lpFileName); - handle = _lopen (lpFileName, wStyle); - if (handle == -1) { - /* Try again with WindowsPath */ - if (FindFile(buf, sizeof(buf), lpFileName, NULL, WindowsPath) != NULL) { - handle = _lopen (buf, wStyle); - } - } - close(handle); - return handle; - } - if (flags & OF_DELETE) - { - printf("OpenFile // OF_DELETE '%s' !\n", lpFileName); - return unlink(lpFileName); - } - else - { - int handle; - char *UnixFileName; - if ((UnixFileName = GetUnixFileName(lpFileName)) == NULL) - return HFILE_ERROR; - handle = open(UnixFileName, base, 0666); - if (handle == -1) { - /* Try again with WindowsPath */ - if (FindFile(buf, sizeof(buf), lpFileName, NULL, WindowsPath) != NULL) { -#ifdef DEBUG_FILE - printf("OpenFile // file '%s' found !\n", buf); -#endif - UnixFileName = buf; - handle = open(UnixFileName, base, 0666); - } - } + if (!(action & OF_REOPEN)) + strcpy(ofs->szPathName, lpFileName); + ofs->cBytes = sizeof(OFSTRUCT); + ofs->fFixedDisk = FALSE; + ofs->nErrCode = 0; + *((int*)ofs->reserved) = 0; -#ifdef DEBUG_FILE - fprintf(stderr, "OpenFile: returning %04.4x\n", handle); -#endif + if ((unixfilename = GetUnixFileName (ofs->szPathName)) == NULL) + { + errno_to_doserr(); + ofs->nErrCode = ExtendedError; + return -1; + } + handle = open (ofs->szPathName, (wStyle & 0x0003) | O_CREAT, 0x666); + if (handle == -1) + { + errno_to_doserr(); + ofs->nErrCode = ExtendedError; + } + return handle; + } - if (handle == -1) - return HFILE_ERROR; + + /* If path isn't given, try to find the file. */ + + if (!(action & OF_REOPEN)) + { + if( !( index(lpFileName,'\\') || index(lpFileName,'/') || + index(lpFileName,':'))) + while(1) + { + char temp[MAX_PATH+1]; + strcpy (filename, lpFileName); + if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) ) + break; + GetWindowsDirectory (filename,MAX_PATH); + if (filename[1] != ':') + strcat(filename,'\\'); + strcat (filename, lpFileName); + if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) ) + break; + GetSystemDirectory (filename,MAX_PATH); + if (filename[1] != ':') + strcat(filename,'\\'); + strcat (filename, lpFileName); + if ( (!stat(GetUnixFileName(filename), &s)) && (S_ISREG(s.st_mode)) ) + break; + if (!FindFile(temp,MAX_PATH,lpFileName,NULL,WindowsPath)) + { + strcpy(filename, GetDosFileName(temp)); + break; + } + strcpy (filename, lpFileName); + break; + } else - return handle; + strcpy (filename,lpFileName); + + ofs->cBytes = sizeof(OFSTRUCT); + ofs->fFixedDisk = FALSE; + strcpy(ofs->szPathName, filename); + ofs->nErrCode = 0; + if (!(action & OF_VERIFY)) + *((int*)ofs->reserved) = 0; } + + + if (action & OF_PARSE) + return 0; + + if (action & OF_DELETE) + return unlink(ofs->szPathName); + + + /* Now on to getting some information about that file */ + + if (res = stat(GetUnixFileName(ofs->szPathName), &s)) + { + errno_to_doserr(); + ofs->nErrCode = ExtendedError; + return -1; + } + + now = localtime (&s.st_mtime); + + if (action & OF_VERIFY) + verify_time = *((int*)ofs->reserved); + + *((WORD*)(&ofs->reserved[2]))= + ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + (now->tm_sec / 2)); + *((WORD*)(&ofs->reserved[0]))= + ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday); + + if (action & OF_EXIST) + return 0; + + if (action & OF_VERIFY) + return (verify_time != *((int*)ofs->reserved)); + + + /* Now we are actually going to open the file. According to Microsoft's + Knowledge Basis, this is done by calling int 21h, ax=3dh. */ + + EAX = 0x00003d00; + EAX = (EAX & 0xffffff0f) | (wStyle & 0x0070); /* Handle OF_SHARE_xxx etc. */ + EAX = (EAX & 0xfffffff0) | (wStyle & 0x0003); /* Handle OF_READ etc. */ + DS = segment (ofs->szPathName); + EDX = (EDX & 0xffff0000) | offset (ofs->szPathName); + + OpenExistingFile (context); + + if (EFL & 0x00000001) /* Cflag */ + { + ofs->nErrCode = (AX & 0x00ff); + return -1; + } + + return AX; } /************************************************************************** diff --git a/misc/lstr.c b/misc/lstr.c index 361ea10b699..28ec8c49dbe 100644 --- a/misc/lstr.c +++ b/misc/lstr.c @@ -12,8 +12,10 @@ static char Copyright[] = "Copyright Yngvi Sigurjonsson (yngvi@hafro.is), 1993" #include "regfunc.h" #include "windows.h" +#define ToUpper(c) toupper(c) +#define ToLower(c) tolower(c) - /* Funny to divide them between user and kernel. */ +/* Funny to divide them between user and kernel. */ /* KERNEL.89 */ LPSTR lstrcat(LPSTR target,LPCSTR source) @@ -58,44 +60,50 @@ INT lstrlen(LPCSTR str) return strlen(str); } - -/* AnsiUpper USER.431 */ -char FAR* AnsiUpper(char FAR* strOrChar) +/* IsCharAlpha USER 433 */ +BOOL IsCharAlpha(char ch) { - /* I am not sure if the locale stuff works with toupper, but then again - I am not sure if the Linux libc locale stuffs works at all */ -/* if((int)strOrChar<256) - return (char FAR*) toupper((int)strOrChar); - else { - int i; - for(i=0;(i<65536) && strOrChar[i];i++) - strOrChar[i]=toupper(strOrChar[i]); - return strOrChar; - } */ - int i; - for (i = 0; (i < 65536 && strOrChar[i]);i++) - strOrChar[i] = (strOrChar[i] >= 'a' && strOrChar[i] <= 'z') ? - strOrChar[i] - ('a' - 'A') : strOrChar[i]; - return strOrChar; + return isalpha(ch); /* This is probably not right for NLS */ } -/* AnsiLower USER.432 */ -char FAR* AnsiLower(char FAR* strOrChar) +/* IsCharAlphanumeric USER 434 */ +BOOL IsCharAlphanumeric(char ch) { - /* I am not sure if the locale stuff works with tolower, but then again + return (ch<'0')?0:(ch<'9'); +} + +/* IsCharUpper USER 435 */ +BOOL IsCharUpper(char ch) +{ + return isupper(ch); +} + +/* IsCharLower USER 436 */ +BOOL IsCharLower(char ch) +{ + return islower(ch); +} + +/* AnsiUpper USER.431 */ +LPSTR AnsiUpper(LPSTR strOrChar) +{ + char *s = strOrChar; + /* I am not sure if the locale stuff works with toupper, but then again I am not sure if the Linux libc locale stuffs works at all */ -/* if((int)strOrChar<256) - return (char FAR*)tolower((int)strOrChar); - else { - int i; - for(i=0;(i<65536)&&strOrChar[i];i++) - strOrChar[i]=tolower(strOrChar[i]); - return strOrChar; - }*/ - int i; - for (i = 0; (i < 65536 && strOrChar[i]);i++) - strOrChar[i] = (strOrChar[i] >= 'A' && strOrChar[i] <= 'Z') ? - strOrChar[i] + ('a' - 'A') : strOrChar[i]; + + /* uppercase only one char if strOrChar < 0x10000 */ + if(HIWORD((DWORD)strOrChar)) { + while (*s) { + if (IsCharLower(*s)) + *s = ToUpper(*s); + s++; + } + return strOrChar; + } else + if (IsCharLower((char) strOrChar)) + return (LPSTR) ToUpper(strOrChar); + else + return (LPSTR) strOrChar; } /* AnsiUpperBuff USER.437 */ @@ -109,6 +117,28 @@ UINT AnsiUpperBuff(LPSTR str,UINT len) return i; } +/* AnsiLower USER.432 */ +LPSTR AnsiLower(LPSTR strOrChar) +{ + char *s = strOrChar; + /* I am not sure if the locale stuff works with toupper, but then again + I am not sure if the Linux libc locale stuffs works at all */ + + /* lowercase only one char if strOrChar < 0x10000 */ + if(HIWORD((DWORD)strOrChar)) { + while (*s) { + if (IsCharUpper(*s)) + *s = ToLower(*s); + s++; + } + return strOrChar; + } else + if (IsCharUpper((char) strOrChar)) + return (LPSTR) ToLower(strOrChar); + else + return (LPSTR) strOrChar; +} + /* AnsiLowerBuff USER.438 */ UINT AnsiLowerBuff(LPSTR str,UINT len) { @@ -134,29 +164,6 @@ char FAR* AnsiPrev(/*const*/ char FAR* start,char FAR* current) return (current==start)?start:current-1; } -/* IsCharAlpha USER 433 */ -BOOL IsCharAlpha(char ch) -{ - return isalpha(ch); /* This is probably not right for NLS */ -} -/* IsCharAlphanumeric USER 434 */ -BOOL IsCharAlphanumeric(char ch) -{ - return (ch<'0')?0:(ch<'9'); -} - -/* IsCharUpper USER 435 */ -BOOL IsCharUpper(char ch) -{ - return isupper(ch); -} - -/* IsCharUpper USER 436 */ -BOOL IsCharLower(char ch) -{ - return islower(ch); -} - static char Oem2Ansi[256]; static char Ansi2Oem[256]; diff --git a/misc/spy.c b/misc/spy.c index c52db357809..efb2210c551 100644 --- a/misc/spy.c +++ b/misc/spy.c @@ -153,7 +153,8 @@ const char *MessageTypeNames[SPY_MAX_MSGNUM + 1] = "WM_TIMER", /* 0x0113 */ "WM_HSCROLL", /* 0x0114 */ "WM_VSCROLL", /* 0x0115 */ - NULL, NULL, + "WM_INITMENU", /* 0x0116 */ + "WM_INITMENUPOPUP", /* 0x0117 */ "WM_SYSTIMER", /* 0x0118 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/misc/user.c b/misc/user.c index cce820e0c8a..609e5ec700c 100644 --- a/misc/user.c +++ b/misc/user.c @@ -17,6 +17,7 @@ MDESC *USER_Heap = NULL; extern BOOL ATOM_Init(); extern BOOL GDI_Init(); extern void SYSMETRICS_Init(); +extern BOOL MENU_Init(); extern BOOL WIN_CreateDesktopWindow(); #ifndef WINELIB @@ -69,6 +70,9 @@ USER_InitApp(int hInstance) /* Initialize dialog manager */ if (!DIALOG_Init()) return 0; + /* Initialize menus */ + if (!MENU_Init()) return 0; + /* Create system message queue */ queueSize = GetProfileInt( "windows", "TypeAhead", 120 ); if (!MSG_CreateSysMsgQueue( queueSize )) return 0; diff --git a/misc/winsocket.c b/misc/winsocket.c index cd7fb53c2a0..5195e2a0696 100644 --- a/misc/winsocket.c +++ b/misc/winsocket.c @@ -136,8 +136,47 @@ static WORD errno_to_wsaerrno(void) { wsa_errno = wsaerrno(); } - -SOCKET Winsock_accept(SOCKET s, struct sockaddr FAR *addr, INT FAR *addrlen) + +static void convert_sockopt(INT *level, INT *optname) +{ +/* $%#%!@! why couldn't they use the same values for both winsock and unix ? */ + + switch (*level) { + case -1: + *level = SOL_SOCKET; + switch (*optname) { + case 0x01: *optname = SO_DEBUG; + break; + case 0x04: *optname = SO_REUSEADDR; + break; + case 0x08: *optname = SO_KEEPALIVE; + break; + case 0x10: *optname = SO_DONTROUTE; + break; + case 0x20: *optname = SO_BROADCAST; + break; + case 0x80: *optname = SO_LINGER; + break; + case 0x100: *optname = SO_OOBINLINE; + break; + case 0x1001: *optname = SO_SNDBUF; + break; + case 0x1002: *optname = SO_RCVBUF; + break; + case 0x1007: *optname = SO_ERROR; + break; + case 0x1008: *optname = SO_TYPE; + break; + default: + fprintf(stderr, "convert_sockopt() unknown optname %d\n", optname); + break; + } + break; + case 6: *optname = IPPROTO_TCP; + } +} + +SOCKET Winsock_accept(SOCKET s, struct sockaddr *addr, INT *addrlen) { int sock; @@ -152,7 +191,7 @@ SOCKET Winsock_accept(SOCKET s, struct sockaddr FAR *addr, INT FAR *addrlen) return sock; } -INT Winsock_bind(SOCKET s, struct sockaddr FAR *name, INT namelen) +INT Winsock_bind(SOCKET s, struct sockaddr *name, INT namelen) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen); @@ -181,7 +220,7 @@ INT Winsock_closesocket(SOCKET s) return 0; } -INT Winsock_connect(SOCKET s, struct sockaddr FAR *name, INT namelen) +INT Winsock_connect(SOCKET s, struct sockaddr *name, INT namelen) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen); @@ -195,7 +234,7 @@ INT Winsock_connect(SOCKET s, struct sockaddr FAR *name, INT namelen) return 0; } -INT Winsock_getpeername(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen) +INT Winsock_getpeername(SOCKET s, struct sockaddr *name, INT *namelen) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen); @@ -209,7 +248,7 @@ INT Winsock_getpeername(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen) return 0; } -INT Winsock_getsockname(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen) +INT Winsock_getsockname(SOCKET s, struct sockaddr *name, INT *namelen) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen); @@ -221,12 +260,15 @@ INT Winsock_getsockname(SOCKET s, struct sockaddr FAR *name, INT FAR *namelen) return 0; } -INT Winsock_getsockopt(SOCKET s, INT loptname, char FAR *optval, INT FAR *optlen) +INT +Winsock_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen) { #ifdef DEBUG_WINSOCK - fprintf(stderr, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, loptname, (int) optval, (int) *optlen); + fprintf(stderr, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen); #endif - if (getsockopt(s, 0, (int) loptname, optval, (int *) optlen) < 0) { + convert_sockopt(&level, &optname); + + if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) { errno_to_wsaerrno(); return SOCKET_ERROR; } @@ -243,7 +285,7 @@ u_short Winsock_htons(u_short hostshort) return( htons(hostshort) ); } -u_long Winsock_inet_addr(char FAR *cp) +u_long Winsock_inet_addr(char *cp) { return( inet_addr(cp) ); } @@ -266,7 +308,7 @@ char *Winsock_inet_ntoa(struct in_addr in) return (char *) &heap->ntoa_buffer; } -INT Winsock_ioctlsocket(SOCKET s, long cmd, u_long FAR *argp) +INT Winsock_ioctlsocket(SOCKET s, long cmd, u_long *argp) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_ioctl: socket %d, cmd %d, ptr %8x\n", s, cmd, (int) argp); @@ -302,7 +344,7 @@ u_short Winsock_ntohs(u_short netshort) return( ntohs(netshort) ); } -INT Winsock_recv(SOCKET s, char FAR *buf, INT len, INT flags) +INT Winsock_recv(SOCKET s, char *buf, INT len, INT flags) { int length; @@ -317,8 +359,8 @@ INT Winsock_recv(SOCKET s, char FAR *buf, INT len, INT flags) return length; } -INT Winsock_recvfrom(SOCKET s, char FAR *buf, INT len, INT flags, - struct sockaddr FAR *from, int FAR *fromlen) +INT Winsock_recvfrom(SOCKET s, char *buf, INT len, INT flags, + struct sockaddr *from, int *fromlen) { int length; @@ -333,8 +375,8 @@ INT Winsock_recvfrom(SOCKET s, char FAR *buf, INT len, INT flags, return length; } -INT Winsock_select(INT nfds, fd_set FAR *readfds, fd_set FAR *writefds, - fd_set FAR *exceptfds, struct timeval FAR *timeout) +INT Winsock_select(INT nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_select: fd # %d, ptr %8x, ptr %8x, ptr %*X\n", nfds, readfds, writefds, exceptfds); @@ -343,7 +385,7 @@ INT Winsock_select(INT nfds, fd_set FAR *readfds, fd_set FAR *writefds, return(select(nfds, readfds, writefds, exceptfds, timeout)); } -INT Winsock_send(SOCKET s, char FAR *buf, INT len, INT flags) +INT Winsock_send(SOCKET s, char *buf, INT len, INT flags) { int length; @@ -358,8 +400,8 @@ INT Winsock_send(SOCKET s, char FAR *buf, INT len, INT flags) return length; } -INT Winsock_sendto(SOCKET s, char FAR *buf, INT len, INT flags, - struct sockaddr FAR *to, INT tolen) +INT Winsock_sendto(SOCKET s, char *buf, INT len, INT flags, + struct sockaddr *to, INT tolen) { int length; @@ -374,13 +416,14 @@ INT Winsock_sendto(SOCKET s, char FAR *buf, INT len, INT flags, return length; } -INT Winsock_setsockopt(SOCKET s, INT level, INT optname, const char FAR *optval, +INT Winsock_setsockopt(SOCKET s, INT level, INT optname, const char *optval, INT optlen) { #ifdef DEBUG_WINSOCK fprintf(stderr, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen); #endif - + convert_sockopt(&level, &optname); + if (setsockopt(s, level, optname, optval, optlen) < 0) { errno_to_wsaerrno(); return SOCKET_ERROR; @@ -430,7 +473,7 @@ SOCKET Winsock_socket(INT af, INT type, INT protocol) return sock; } -struct hostent *Winsock_gethostbyaddr(const char FAR *addr, INT len, INT type) +struct hostent *Winsock_gethostbyaddr(const char *addr, INT len, INT type) { struct hostent *host; @@ -447,7 +490,7 @@ struct hostent *Winsock_gethostbyaddr(const char FAR *addr, INT len, INT type) return (struct hostent *) &heap->hostent_addr; } -struct hostent *Winsock_gethostbyname(const char FAR *name) +struct hostent *Winsock_gethostbyname(const char *name) { struct hostent *host; @@ -464,7 +507,7 @@ struct hostent *Winsock_gethostbyname(const char FAR *name) return (struct hostent *) &heap->hostent_name; } -int Winsock_gethostname(char FAR *name, INT namelen) +int Winsock_gethostname(char *name, INT namelen) { #ifdef DEBUG_WINSOCK @@ -478,7 +521,7 @@ int Winsock_gethostname(char FAR *name, INT namelen) return 0; } -struct protoent *Winsock_getprotobyname(char FAR *name) +struct protoent *Winsock_getprotobyname(char *name) { struct protoent *proto; @@ -512,7 +555,7 @@ struct protoent *Winsock_getprotobynumber(INT number) return (struct protoent *) &heap->protoent_number; } -struct servent *Winsock_getservbyname(const char FAR *name, const char FAR *proto) +struct servent *Winsock_getservbyname(const char *name, const char *proto) { struct servent *service; @@ -529,7 +572,7 @@ struct servent *Winsock_getservbyname(const char FAR *name, const char FAR *prot return (struct servent *) &heap->servent_name; } -struct servent *Winsock_getservbyport(INT port, const char FAR *proto) +struct servent *Winsock_getservbyport(INT port, const char *proto) { struct servent *service; @@ -597,8 +640,8 @@ static void send_message(HANDLE handle, HWND hWnd, u_int wMsg, long lParam) } -HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR *addr, - INT len, INT type, char FAR *buf, INT buflen) +HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char *addr, + INT len, INT type, char *buf, INT buflen) { HANDLE handle; struct hostent *host; @@ -619,8 +662,8 @@ HANDLE WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR *addr, } -HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char FAR *name, - char FAR *buf, INT buflen) +HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char *name, + char *buf, INT buflen) { HANDLE handle; struct hostent *host; @@ -641,8 +684,8 @@ HANDLE WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char FAR *name, } -HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char FAR *name, - char FAR *buf, INT buflen) +HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char *name, + char *buf, INT buflen) { HANDLE handle; struct protoent *proto; @@ -664,7 +707,7 @@ HANDLE WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, const char FAR *name, HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, - char FAR *buf, INT buflen) + char *buf, INT buflen) { HANDLE handle; struct protoent *proto; @@ -685,8 +728,8 @@ HANDLE WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, } -HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char FAR *name, - const char FAR *proto, char FAR *buf, INT buflen) +HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char *name, + const char *proto, char *buf, INT buflen) { HANDLE handle; struct servent *service; @@ -707,8 +750,8 @@ HANDLE WSAAsyncGetServByName(HWND hWnd, u_int wMsg, const char FAR *name, } -HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char FAR - *proto, char FAR *buf, INT buflen) +HANDLE WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, const char + *proto, char *buf, INT buflen) { HANDLE handle; struct servent *service; diff --git a/miscemu/emulate.c b/miscemu/emulate.c index 1b695031ea6..78b49a92c93 100644 --- a/miscemu/emulate.c +++ b/miscemu/emulate.c @@ -28,19 +28,19 @@ WIN87_fpmath() } -int +void WIN87_WinEm87Info(struct Win87EmInfoStruct *pWIS, int cbWin87EmInfoStruct) { printf( "__WinEm87Info(%p,%d)\n",pWIS,cbWin87EmInfoStruct); } -int +void WIN87_WinEm87Restore(void *pWin87EmSaveArea, int cbWin87EmSaveArea) { printf( "__WinEm87Restore(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea); } -int +void WIN87_WinEm87Save(void *pWin87EmSaveArea, int cbWin87EmSaveArea) { printf( "__WinEm87Save(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea); diff --git a/miscemu/int10.c b/miscemu/int10.c index 1d49f5ed071..632f27983d9 100644 --- a/miscemu/int10.c +++ b/miscemu/int10.c @@ -1,6 +1,6 @@ #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" void IntBarf(int i, struct sigcontext_struct *context) @@ -13,23 +13,22 @@ void IntBarf(int i, struct sigcontext_struct *context) int do_int10(struct sigcontext_struct *context) { - switch((context->sc_eax >> 8) & 0xff) - { + switch(AH) { case 0x0f: - EAX = (EAX & 0xffffff00) | 0x5b; + AL = 0x5b; break; case 0x12: - if ((EBX & 0xff) == 0x10) { - EBX = (EBX & 0xffff0000) | 0x0003; - ECX = (ECX & 0xffff0000) | 0x0009; + if (BL == 0x10) { + BX = 0x0003; + CX = 0x0009; } break; case 0x1a: - EBX = (EBX & 0xffff0000) | 0x0008; + BX = 0x0008; break; - + default: IntBarf(0x10, context); }; diff --git a/miscemu/int13.c b/miscemu/int13.c index 55fb5b23e1b..8fb128e6d03 100644 --- a/miscemu/int13.c +++ b/miscemu/int13.c @@ -1,29 +1,28 @@ #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" int do_int13(struct sigcontext_struct *context) { - switch((context->sc_eax >> 8) & 0xff) - { + switch(AH) { case 0x00: /* RESET DISK SYSTEM */ case 0x04: /* VERIFY DISK SECTOR(S) */ - EAX = (EAX & 0xffff00ff); + AH = 0; break; case 0x05: /* FORMAT TRACK */ - EAX = (EAX & 0xffff00ff) | 0x0c; + AH = 0x0c; SetCflag; break; case 0x06: /* FORMAT TRACK AND SET BAD SECTOR FLAGS */ case 0x07: /* FORMAT DRIVE STARTING AT GIVEN TRACK */ - EAX = (EAX & 0xffff00ff) | 0x0c; + AH = 0x0c; break; case 0x08: /* GET DRIVE PARAMETERS */ - EAX = (EAX & 0xffff00ff) | ((EDX & 0x00000080)? 0x07: 0x01); + AH = (DL & 0x80) ? 0x07 : 0x01; SetCflag; break; @@ -33,20 +32,17 @@ int do_int13(struct sigcontext_struct *context) case 0x10: /* CHECK IF DRIVE READY */ case 0x11: /* RECALIBRATE DRIVE */ case 0x14: /* CONTROLLER INTERNAL DIAGNOSTIC */ - EAX = (EAX & 0xffff00ff); + AH = 0; break; case 0x0e: /* READ SECTOR BUFFER (XT only) */ case 0x0f: /* WRITE SECTOR BUFFER (XT only) */ case 0x12: /* CONTROLLER RAM DIAGNOSTIC (XT,PS) */ case 0x13: /* DRIVE DIAGNOSTIC (XT,PS) */ - EAX = (EAX & 0xffff00ff) | 0x01; + AH = 0x01; SetCflag; break; - - - default: IntBarf(0x13, context); }; diff --git a/miscemu/int15.c b/miscemu/int15.c index 054a7e3c55e..67a0b7acedd 100644 --- a/miscemu/int15.c +++ b/miscemu/int15.c @@ -1,12 +1,11 @@ #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" int do_int15(struct sigcontext_struct *context) { - switch((context->sc_eax >> 8) & 0xff) - { + switch(AH) { case 0xc0: default: diff --git a/miscemu/int16.c b/miscemu/int16.c index 88ff49d4ce6..33ecef58237 100644 --- a/miscemu/int16.c +++ b/miscemu/int16.c @@ -1,12 +1,11 @@ #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" int do_int16(struct sigcontext_struct *context) { - switch((context->sc_eax >> 8) & 0xff) - { + switch(AH) { case 0xc0: default: diff --git a/miscemu/int1a.c b/miscemu/int1a.c index 95b19bdd2bc..f43fef3c30a 100644 --- a/miscemu/int1a.c +++ b/miscemu/int1a.c @@ -1,7 +1,7 @@ #include #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" #include "options.h" @@ -23,13 +23,13 @@ int do_int1A(struct sigcontext_struct * context){ AX, BX, CX, DX, SI, DI, DS, ES); } - switch((context->sc_eax >> 8) & 0xff){ + switch(AH) { case 0: ltime = time(NULL); ticks = (int) (ltime * HZ); - context->sc_ecx = ticks >> 16; - context->sc_edx = ticks & 0x0000FFFF; - context->sc_eax = 0; /* No midnight rollover */ + CX = ticks >> 16; + DX = ticks & 0x0000FFFF; + AX = 0; /* No midnight rollover */ printf("int1a_00 // ltime=%ld ticks=%ld\n", ltime, ticks); break; @@ -37,14 +37,14 @@ int do_int1A(struct sigcontext_struct * context){ ltime = time(NULL); bdtime = localtime(<ime); - context->sc_ecx = (BIN_TO_BCD(bdtime->tm_hour)<<8) | BIN_TO_BCD(bdtime->tm_min); - context->sc_edx = (BIN_TO_BCD(bdtime->tm_sec)<<8); + CX = (BIN_TO_BCD(bdtime->tm_hour)<<8) | BIN_TO_BCD(bdtime->tm_min); + DX = (BIN_TO_BCD(bdtime->tm_sec)<<8); case 4: ltime = time(NULL); bdtime = localtime(<ime); - context->sc_ecx = (BIN_TO_BCD(bdtime->tm_year/100)<<8) | BIN_TO_BCD((bdtime->tm_year-1900)%100); - context->sc_edx = (BIN_TO_BCD(bdtime->tm_mon)<<8) | BIN_TO_BCD(bdtime->tm_mday); + CX = (BIN_TO_BCD(bdtime->tm_year/100)<<8) | BIN_TO_BCD((bdtime->tm_year-1900)%100); + DX = (BIN_TO_BCD(bdtime->tm_mon)<<8) | BIN_TO_BCD(bdtime->tm_mday); break; /* setting the time,date or RTC is not allow -EB */ diff --git a/miscemu/int21.c b/miscemu/int21.c index 2485f59a607..5ed34e0196b 100644 --- a/miscemu/int21.c +++ b/miscemu/int21.c @@ -7,15 +7,20 @@ #include #include #include +#include #include #include +#include +#include #include #include +#include #include "prototypes.h" #include "regfunc.h" #include "windows.h" #include "wine.h" #include "msdos.h" +#include "registers.h" #include "options.h" WORD ExtendedError, CodePage = 437; @@ -29,6 +34,9 @@ struct DosHeap { }; static struct DosHeap *heap; +WORD sharing_retries = 3; /* number of retries at sharing violation */ +WORD sharing_pause = 1; /* pause between retries */ + extern char TempDirectory[]; static int Error(int e, int class, int el) @@ -41,7 +49,7 @@ static int Error(int e, int class, int el) return e; } -static void errno_to_doserr(void) +void errno_to_doserr(void) { switch (errno) { case EAGAIN: @@ -138,28 +146,28 @@ static void GetFreeDiskSpace(struct sigcontext_struct *context) int drive; long size,available; - if (!(EDX & 0xff)) + if (DL == 0) drive = DOS_GetDefaultDrive(); else - drive = (EDX & 0xff) - 1; + drive = DL - 1; if (!DOS_ValidDrive(drive)) { Error(InvalidDrive, EC_MediaError , EL_Disk); - EAX |= 0xffffL; + AX = 0xffff; return; } if (!DOS_GetFreeSpace(drive, &size, &available)) { Error(GeneralFailure, EC_MediaError , EL_Disk); - EAX |= 0xffffL; + AX = 0xffff; return; } - EAX = (EAX & 0xffff0000) | 4; - ECX = (ECX & 0xffff0000) | 512; + AX = 4; + CX = 512; - EBX = (EBX & 0xffff0000) | (available / (CX * AX)); - EDX = (EDX & 0xffff0000) | (size / (CX * AX)); + BX = (available / (CX * AX)); + DX = (size / (CX * AX)); Error (0,0,0); } @@ -169,43 +177,41 @@ static void GetDriveAllocInfo(struct sigcontext_struct *context) long size, available; BYTE mediaID; - drive = EDX & 0xffL; - - if (!DOS_ValidDrive(drive)) { - EAX = (EAX & 0xffff0000) | 4; - ECX = (ECX & 0xffff0000) | 512; - EDX = (EDX & 0xffff0000); + if (!DOS_ValidDrive(DL)) { + AX = 4; + CX = 512; + DX = 0; Error (InvalidDrive, EC_MediaError, EL_Disk); return; } - if (!DOS_GetFreeSpace(drive, &size, &available)) { + if (!DOS_GetFreeSpace(DL, &size, &available)) { Error(GeneralFailure, EC_MediaError , EL_Disk); - EAX |= 0xffffL; + AX = 0xffff; return; } - EAX = (EAX & 0xffff0000) | 4; - ECX = (ECX & 0xffff0000) | 512; - EDX = (EDX & 0xffff0000) | (size / (CX * AX)); + EAX = 4; + ECX = 512; + EDX = (size / (CX * AX)); mediaID = 0xf0; DS = segment(mediaID); - EBX = offset(mediaID); + BX = offset(mediaID); Error (0,0,0); } static void GetDefDriveAllocInfo(struct sigcontext_struct *context) { - EDX = DOS_GetDefaultDrive(); + DX = DOS_GetDefaultDrive(); GetDriveAllocInfo(context); } static void GetDrivePB(struct sigcontext_struct *context) { Error (InvalidDrive, EC_MediaError, EL_Disk); - EAX = (EAX & 0xffff0000) | 0xffL; + AX = 0x00ff; /* I'm sorry but I only got networked drives :-) */ } @@ -217,7 +223,7 @@ static void ReadFile(struct sigcontext_struct *context) /* can't read from stdout / stderr */ if ((BX == 1) || (BX == 2)) { Error (InvalidHandle, EL_Unknown, EC_Unknown); - EAX = (EAX & 0xffff0000) | InvalidHandle; + AX = InvalidHandle; SetCflag; return; } @@ -226,19 +232,19 @@ static void ReadFile(struct sigcontext_struct *context) if (BX == 0) { *ptr = EOF; Error (0,0,0); - EAX = (EAX & 0xffff0000) | 1; + AX = 1; ResetCflag; return; } else { size = read(BX, ptr, CX); if (size == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; SetCflag; return; } Error (0,0,0); - EAX = (EAX & 0xffff0000) | size; + AX = size; ResetCflag; } } @@ -264,24 +270,24 @@ static void WriteFile(struct sigcontext_struct *context) fflush(stderr); Error (0,0,0); - EAX = (EAX & 0xffffff00) | CX; + AL = CX; ResetCflag; } else { size = write(BX, ptr , CX); if (size == 0) { Error (WriteFault, EC_Unknown, EL_Unknown); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; return; } if (size == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; SetCflag; return; } Error (0,0,0); - EAX = (EAX & 0xffff0000) | size; + AX = size; ResetCflag; } } @@ -290,7 +296,7 @@ static void SeekFile(struct sigcontext_struct *context) { off_t status, fileoffset; - switch (EAX & 0xff) { + switch (AL) { case 1: fileoffset = SEEK_CUR; break; case 2: fileoffset = SEEK_END; @@ -302,41 +308,39 @@ static void SeekFile(struct sigcontext_struct *context) status = lseek(BX, (CX * 0x100) + DX, fileoffset); if (status == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; SetCflag; + AL = ExtendedError; SetCflag; return; } Error (0,0,0); - EAX = (EAX & 0xffff0000L) | (status & 0xffff); - EDX = (EDX & 0xffff0000L) | ((status >> 16) & 0xffff); - + AX = (status & 0xffff); + DX = ((status >> 16) & 0xffff); + ResetCflag; } static void ioctlGetDeviceInfo(struct sigcontext_struct *context) { - WORD handle = EBX & 0xffff; - - switch (handle) { + switch (BX) { case 0: case 1: case 2: - EDX = (EDX & 0xffff0000) | 0x80d3; + DX = 0x80d3; break; default: { struct stat sbuf; - if (fstat(handle, &sbuf) < 0) + if (fstat(BX, &sbuf) < 0) { IntBarf(0x21, context); - EDX = (EDX & 0xffff0000) | 0x50; + DX = 0x50; SetCflag; return; } /* This isn't the right answer, but should be close enough. */ - EDX = (EDX & 0xffff0000) | 0x0943; + DX = 0x0943; } } ResetCflag; @@ -347,16 +351,16 @@ static void ioctlGenericBlkDevReq(struct sigcontext_struct *context) BYTE *dataptr = pointer(DS, DX); int drive; - if (!(EBX & 0xff)) + if (BL == 0) drive = DOS_GetDefaultDrive(); else - drive = (EBX & 0xff) - 1; + drive = BL - 1; - if ((ECX & 0xff00) != 0x0800) { + if (CH != 0x08) { IntBarf(0x21, context); return; } - switch (ECX & 0xff) { + switch (CL) { case 0x60: /* get device parameters */ /* used by w4wgrp's winfile */ dataptr[0] = 0x04; @@ -374,7 +378,7 @@ static void ioctlGenericBlkDevReq(struct sigcontext_struct *context) setword(&dataptr[4], 80); /* # of cylinders */ } CreateBPB(drive, &dataptr[7]); - EAX = (EAX & 0xfffff00); + AL = 0; ResetCflag; return; default: @@ -390,50 +394,52 @@ static void GetSystemDate(struct sigcontext_struct *context) ltime = time(NULL); now = localtime(<ime); - ECX = (ECX & 0xffff0000) | (now->tm_year + 1900); - EDX = (EDX & 0xffff0000) | ((now->tm_mon + 1) << 8) | now->tm_mday; - EAX = (EAX & 0xffff0000) | now->tm_wday; + CX = now->tm_year + 1900; + DX = ((now->tm_mon + 1) << 8) | now->tm_mday; + AX = now->tm_wday; } static void GetSystemTime(struct sigcontext_struct *context) { struct tm *now; - time_t ltime; + struct timeval tv; - ltime = time(NULL); - now = localtime(<ime); + gettimeofday(&tv,NULL); /* Note use of gettimeofday(), instead of time() */ + now = localtime(&tv.tv_sec); - ECX = (ECX & 0xffffff00) | (now->tm_hour << 8) | now->tm_min; - EDX = (EDX & 0xffffff00) | now->tm_sec << 8; + CX = (now->tm_hour<<8) | now->tm_min; + DX = (now->tm_sec<<8) | tv.tv_usec/10000; + /* Note hundredths of seconds */ } static void GetExtendedErrorInfo(struct sigcontext_struct *context) { - EAX = (EAX & 0xffffff00) | ExtendedError; - EBX = (EBX & 0xffff0000) | (ErrorClass << 8) | Action; - ECX = (ECX & 0xffff00ff) | (ErrorLocus << 8); + AL = ExtendedError; + BX = (ErrorClass << 8) | Action; + CH = ErrorLocus << 8; } static void CreateFile(struct sigcontext_struct *context) { int handle; - if ((handle = open(GetUnixFileName( pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) { + if ((handle = open(GetUnixFileName( pointer(DS,DX)), + O_CREAT | O_TRUNC | O_RDWR )) == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; SetCflag; return; } Error (0,0,0); - EBX = (EBX & 0xffff0000) | handle; - EAX = (EAX & 0xffffff00) | NoError; + EAX = (EAX & 0xffff0000) | handle; ResetCflag; } -static void OpenExistingFile(struct sigcontext_struct *context) +void OpenExistingFile(struct sigcontext_struct *context) { int handle; int mode; + int lock; switch (AX & 0x0007) { @@ -450,16 +456,66 @@ static void OpenExistingFile(struct sigcontext_struct *context) break; } - fprintf(stderr,"OpenExistingFile (%s)\n", pointer(DS,DX)); - if ((handle = open(GetUnixFileName(pointer(DS,DX)), mode)) == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; SetCflag; return; } + + switch (AX & 0x0070) + { + case 0x00: /* compatability mode */ + case 0x40: /* DENYNONE */ + lock = -1; + break; + + case 0x30: /* DENYREAD */ + fprintf(stderr, + "OpenExistingFile (%s): DENYREAD changed to DENYALL\n", + pointer(DS,DX)); + case 0x10: /* DENYALL */ + lock = LOCK_EX; + break; + + case 0x20: /* DENYWRITE */ + lock = LOCK_SH; + break; + + default: + lock = -1; + } + + if (lock != -1) + { + + int result,retries=sharing_retries; + { + result = flock(handle, lock | LOCK_NB); + if ( retries && (!result) ) + { + int i; + for(i=0;i<32768*((int)sharing_pause);i++) + result++; /* stop the optimizer */ + for(i=0;i<32768*((int)sharing_pause);i++) + result--; + } + } + while( (!result) && (!(retries--)) ); + + if(result) + { + errno_to_doserr(); + EAX = (EAX & 0xffffff00) | ExtendedError; + close(handle); + SetCflag; + return; + } + + } + Error (0,0,0); - EAX = (EBX & 0xffff0000) | handle; + EAX = (EAX & 0xffff0000) | handle; ResetCflag; } @@ -467,12 +523,12 @@ static void CloseFile(struct sigcontext_struct *context) { if (close(BX) == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; SetCflag; return; } Error (0,0,0); - EAX = (EAX & 0xffffff00) | NoError; + AL = NoError; ResetCflag; } @@ -498,13 +554,13 @@ static void MakeDir(struct sigcontext_struct *context) fprintf(stderr,"int21: makedir %s\n", pointer(DS,DX) ); if ((dirname = GetUnixFileName( pointer(DS,DX) ))== NULL) { - EAX = (EAX & 0xffffff00) | CanNotMakeDir; + AL = CanNotMakeDir; SetCflag; return; } if (mkdir(dirname,0) == -1) { - EAX = (EAX & 0xffffff00) | CanNotMakeDir; + AL = CanNotMakeDir; SetCflag; return; } @@ -531,19 +587,19 @@ static void RemoveDir(struct sigcontext_struct *context) fprintf(stderr,"int21: removedir %s\n", pointer(DS,DX) ); if ((dirname = GetUnixFileName( pointer(DS,DX) ))== NULL) { - EAX = (EAX & 0xffffff00) | CanNotMakeDir; + AL = CanNotMakeDir; SetCflag; return; } /* if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) { - EAX = (EAX & 0xffffff00) | CanNotRemoveCwd; + AL = CanNotRemoveCwd; SetCflag; } */ if (rmdir(dirname) == -1) { - EAX = (EAX & 0xffffff00) | CanNotMakeDir; + AL = CanNotMakeDir; SetCflag; } ResetCflag; @@ -558,23 +614,23 @@ static void FindNext(struct sigcontext_struct *context) { struct dosdirent *dp; - dp = (struct dosdirent *)(dta + 0x0d); + memcpy(&dp, dta+0x0d, sizeof(dp)); do { if ((dp = DOS_readdir(dp)) == NULL) { Error(NoMoreFiles, EC_MediaError , EL_Disk); - EAX = (EAX & 0xffffff00) | NoMoreFiles; + AL = NoMoreFiles; SetCflag; return; } } while (*(dta + 0x0c) != dp->attribute); - + setword(&dta[0x16], 0x1234); /* time */ setword(&dta[0x18], 0x1234); /* date */ setdword(&dta[0x1a], dp->filesize); strncpy(dta + 0x1e, dp->filename, 13); - EAX = (EAX & 0xffffff00); + AL; ResetCflag; return; } @@ -589,7 +645,7 @@ static void FindFirst(struct sigcontext_struct *context) if (!DOS_ValidDrive(drive)) { Error(InvalidDrive, EC_MediaError , EL_Disk); - EAX = (EAX & 0xffffff00L) | InvalidDrive; + AL = InvalidDrive; SetCflag; return; } @@ -606,14 +662,14 @@ static void FindFirst(struct sigcontext_struct *context) if (DOS_GetVolumeLabel(drive) != NULL) strncpy(dta + 0x1e, DOS_GetVolumeLabel(drive), 8); - EAX = (EAX & 0xffffff00L); + AL = 0; ResetCflag; return; } if ((dp = DOS_opendir(path)) == NULL) { Error(PathNotFound, EC_MediaError, EL_Disk); - EAX = (EAX & 0xffffff00L) | FileNotFound; + AL = FileNotFound; SetCflag; return; } @@ -629,7 +685,7 @@ static void GetFileDateTime(struct sigcontext_struct *context) struct tm *now; if ((filename = GetUnixFileName( pointer(DS,DX) ))== NULL) { - EAX = (EAX & 0xffffff00) | FileNotFound; + AL = FileNotFound; SetCflag; return; } @@ -637,8 +693,8 @@ static void GetFileDateTime(struct sigcontext_struct *context) now = localtime (&filestat.st_mtime); - ECX = (ECX & 0xffff0000) | ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2); - EDX = (EDX & 0xffff0000) | ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday); + CX = ((now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2); + DX = ((now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday); ResetCflag; } @@ -669,14 +725,14 @@ static void CreateTempFile(struct sigcontext_struct *context) handle = open(GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR); if (handle == -1) { - EAX = (EAX & 0xffffff00) | WriteProtected; + AL = WriteProtected; SetCflag; return; } strcpy(pointer(DS,DX), temp); - EAX = (EAX & 0xffff0000) | handle; + AX = handle; ResetCflag; } @@ -684,13 +740,13 @@ static void CreateNewFile(struct sigcontext_struct *context) { int handle; - if ((handle = open(GetUnixFileName( pointer(DS,DX) ), O_CREAT | O_TRUNC | O_RDWR)) == -1) { - EAX = (EAX & 0xffffff00) | WriteProtected; + if ((handle = open(GetUnixFileName( pointer(DS,DX) ), O_CREAT | O_EXCL | O_RDWR)) == -1) { + AL = WriteProtected; SetCflag; return; } - EAX = (EAX & 0xffff0000) | handle; + AX = handle; ResetCflag; } @@ -698,13 +754,13 @@ static void GetCurrentDirectory(struct sigcontext_struct *context) { int drive; - if ((EDX & 0xff) == 0) + if (DL == 0) drive = DOS_GetDefaultDrive(); else - drive = (EDX & 0xff)-1; + drive = DL - 1; if (!DOS_ValidDrive(drive)) { - EAX = (EAX & 0xffffff00) | InvalidDrive; + AL = InvalidDrive; SetCflag; return; } @@ -719,13 +775,13 @@ static void GetDiskSerialNumber(struct sigcontext_struct *context) BYTE *dataptr = pointer(DS, DX); DWORD serialnumber; - if ((EBX & 0xff) == 0) + if (BL == 0) drive = DOS_GetDefaultDrive(); else - drive = (EBX & 0xff) - 1; + drive = BL - 1; if (!DOS_ValidDrive(drive)) { - EAX = (EAX & 0xffffff00) |InvalidDrive; + AL =InvalidDrive; SetCflag; return; } @@ -737,7 +793,7 @@ static void GetDiskSerialNumber(struct sigcontext_struct *context) strncpy(dataptr + 6, DOS_GetVolumeLabel(drive), 8); strncpy(dataptr + 0x11, "FAT16 ", 8); - EAX = (EAX & 0xffffff00); + AL; ResetCflag; } @@ -747,13 +803,13 @@ static void SetDiskSerialNumber(struct sigcontext_struct *context) BYTE *dataptr = pointer(DS, DX); DWORD serialnumber; - if ((EBX & 0xff) == 0) + if (BL == 0) drive = DOS_GetDefaultDrive(); else - drive = (EBX & 0xff) - 1; + drive = BL - 1; if (!DOS_ValidDrive(drive)) { - EAX = (EAX & 0xffffff00) | InvalidDrive; + AL = InvalidDrive; SetCflag; return; } @@ -762,7 +818,7 @@ static void SetDiskSerialNumber(struct sigcontext_struct *context) (dataptr[4] << 24); DOS_SetSerialNumber(drive, serialnumber); - EAX = (EAX & 0xffffff00) | 1L; + AL = 1L; ResetCflag; } @@ -803,7 +859,7 @@ static void FindFirstFCB(struct sigcontext_struct *context) strncpy(dta, DOS_GetVolumeLabel(drive), 8); *(dta + 0x0b) = FA_DIREC; - EAX = (EAX & 0xffffff00); + AL; return; } } @@ -833,7 +889,7 @@ static void DeleteFileFCB(struct sigcontext_struct *context) if ((dp = DOS_opendir(temp)) == NULL) { Error(InvalidDrive, EC_MediaError , EL_Disk); - EAX = (EAX & 0xffffff00) | 0xffL; + AL = 0xffL; return; } @@ -849,7 +905,7 @@ static void DeleteFileFCB(struct sigcontext_struct *context) /* unlink(GetUnixFileName(temp)); */ } DOS_closedir(dp); - EAX = (EAX & 0xffffff00); + AL; } static void RenameFileFCB(struct sigcontext_struct *context) @@ -875,7 +931,7 @@ static void RenameFileFCB(struct sigcontext_struct *context) if ((dp = DOS_opendir(temp)) == NULL) { Error(InvalidDrive, EC_MediaError , EL_Disk); - EAX = (EAX & 0xffffff00) | 0xffL; + AL = 0xffL; return; } @@ -894,15 +950,95 @@ static void RenameFileFCB(struct sigcontext_struct *context) fprintf(stderr, "int21: renamefile %s -> %s\n", oldname, newname); } DOS_closedir(dp); - EAX = (EAX & 0xffffff00); + AL; } + + +static void fLock (struct sigcontext_struct * context) +{ + struct flock f; + int result,retries=sharing_retries; + + f.l_start = MAKELONG(DX,CX); + f.l_len = MAKELONG(DI,SI); + f.l_whence = 0; + f.l_pid = 0; + + switch ( AX & 0xff ) + { + case 0x00: /* LOCK */ + f.l_type = F_WRLCK; + break; + + case 0x01: /* UNLOCK */ + f.l_type = F_UNLCK; + break; + + default: + EAX = (EAX & 0xffff0000) | 0x0001; + SetCflag; + return; + } + + { + result = fcntl(BX,F_SETLK,&f); + if ( retries && (!result) ) + { + int i; + for(i=0;i<32768*((int)sharing_pause);i++) + result++; /* stop the optimizer */ + for(i=0;i<32768*((int)sharing_pause);i++) + result--; + } + } + while( (!result) && (!(retries--)) ); + + if(result) + { + errno_to_doserr(); + EAX = (EAX & 0xffffff00) | ExtendedError; + SetCflag; + return; + } + + Error (0,0,0); + ResetCflag; +} + + +static void GetFileAttribute (struct sigcontext_struct * context) +{ + char *filename = pointer (DS,DX); + struct stat s; + int res,cx; + + res = stat(GetUnixFileName(filename), &s); + if (res==-1) + { + errno_to_doserr(); + EAX = (EAX & 0xffffff00) | ExtendedError; + SetCflag; + return; + } + + cx = 0; + if (S_ISDIR(s.st_mode)) + cx|=0x10; + if ((S_IWRITE & s.st_mode) != S_IWRITE) + cx|=0x01; + + ECX = (ECX & 0xffff0000) | cx; + ResetCflag; + Error (0,0,0); +} + + + /************************************************************************/ int do_int21(struct sigcontext_struct * context) { - int ah; - if (Options.relay_debug) { printf("int21: AX %04x, BX %04x, CX %04x, DX %04x, " @@ -910,9 +1046,7 @@ int do_int21(struct sigcontext_struct * context) AX, BX, CX, DX, SI, DI, DS, ES); } - ah = (EAX >> 8) & 0xffL; - - if (ah == 0x59) + if (AH == 0x59) { GetExtendedErrorInfo(context); return 1; @@ -920,7 +1054,7 @@ int do_int21(struct sigcontext_struct * context) else { Error (0,0,0); - switch(ah) + switch(AH) { case 0x00: /* TERMINATE PROGRAM */ exit(0); @@ -970,17 +1104,21 @@ int do_int21(struct sigcontext_struct * context) EAX &= 0xff00; break; + case 0x5c: /* "FLOCK" - RECORD LOCKING */ + fLock(context); + break; + case 0x0d: /* DISK BUFFER FLUSH */ ResetCflag; /* dos 6+ only */ break; case 0x0e: /* SELECT DEFAULT DRIVE */ - if (!DOS_ValidDrive(EDX & 0xff)) { + if (!DOS_ValidDrive(DL)) { Error (InvalidDrive, EC_MediaError, EL_Disk); return; } else { - DOS_SetDefaultDrive(EDX & 0xff); - EAX = (EAX &0xffffff00) | MAX_DOS_DRIVES; + DOS_SetDefaultDrive(DL); + AX = MAX_DOS_DRIVES; Error(0,0,0); } break; @@ -998,7 +1136,7 @@ int do_int21(struct sigcontext_struct * context) break; case 0x19: /* GET CURRENT DEFAULT DRIVE */ - EAX = (EAX & 0xffffff00) | DOS_GetDefaultDrive(); + AL = DOS_GetDefaultDrive(); Error (0,0,0); break; @@ -1020,7 +1158,7 @@ int do_int21(struct sigcontext_struct * context) case 0x25: /* SET INTERRUPT VECTOR */ /* Ignore any attempt to set a segment vector */ - fprintf(stderr, "int21: set interrupt vector %2x (%04x:%04x)\n", AX & 0xff, DS, DX); + fprintf(stderr, "int21: set interrupt vector %2x (%04x:%04x)\n", AL, DS, DX); break; case 0x2a: /* GET SYSTEM DATE */ @@ -1033,13 +1171,13 @@ int do_int21(struct sigcontext_struct * context) case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */ ES = segment(dta); - EBX = (EBX & 0xffff0000) | offset(dta); + BX = offset(dta); break; case 0x30: /* GET DOS VERSION */ - EAX = (EAX & 0xffff0000) | DOSVERSION; - EBX = (EBX & 0xffff0000) | 0x0012; /* 0x123456 is Wine's serial # */ - ECX = (ECX & 0xffff0000) | 0x3456; + AX = DOSVERSION; + BX = 0x0012; /* 0x123456 is Wine's serial # */ + CX = 0x3456; break; case 0x31: /* TERMINATE AND STAY RESIDENT */ @@ -1051,9 +1189,9 @@ int do_int21(struct sigcontext_struct * context) break; case 0x33: /* MULTIPLEXED */ - switch (EAX & 0xff) { + switch (AL) { case 0x00: /* GET CURRENT EXTENDED BREAK STATE */ - if (!(EAX & 0xff)) + if (!(AL)) EDX &= 0xff00L; break; @@ -1061,11 +1199,11 @@ int do_int21(struct sigcontext_struct * context) break; case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE*/ - EDX &= 0xff00L; + DL = 0; break; case 0x05: /* GET BOOT DRIVE */ - EDX = (EDX & 0xff00) | 2; + DL = 2; /* c: is Wine's bootdrive */ break; @@ -1081,8 +1219,8 @@ int do_int21(struct sigcontext_struct * context) break; case 0x34: /* GET ADDRESS OF INDOS FLAG */ - ES = (ES & 0xffff0000) | segment(heap->InDosFlag); - EBX = (EBX & 0xffff0000) | offset(heap->InDosFlag); + ES = segment(heap->InDosFlag); + BX = offset(heap->InDosFlag); break; case 0x35: /* GET INTERRUPT VECTOR */ @@ -1090,7 +1228,7 @@ int do_int21(struct sigcontext_struct * context) if anyone ever tries to use it */ fprintf(stderr, "int21: get interrupt vector %2x\n", AX & 0xff); ES = 0; - EBX = 0; + BX = 0; break; case 0x36: /* GET FREE DISK SPACE */ @@ -1098,8 +1236,7 @@ int do_int21(struct sigcontext_struct * context) break; case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */ - EAX &= 0xff00; - EAX |= 0x02; /* no country support available */ + AX = 0x02; /* no country support available */ SetCflag; break; @@ -1138,7 +1275,7 @@ int do_int21(struct sigcontext_struct * context) case 0x41: /* "UNLINK" - DELETE FILE */ if (unlink( GetUnixFileName( pointer(DS,DX)) ) == -1) { errno_to_doserr(); - EAX = (EAX & 0xffffff00) | ExtendedError; + AL = ExtendedError; SetCflag; return; } @@ -1151,11 +1288,10 @@ int do_int21(struct sigcontext_struct * context) break; case 0x43: /* FILE ATTRIBUTES */ - switch (EAX & 0xff) + switch (AL) { case 0x00: - EAX &= 0xfffff00L; - ResetCflag; + GetFileAttribute(context); break; case 0x01: ResetCflag; @@ -1164,18 +1300,27 @@ int do_int21(struct sigcontext_struct * context) break; case 0x44: /* IOCTL */ - switch (EAX & 0xff) + switch (AL) { case 0x00: ioctlGetDeviceInfo(context); break; case 0x09: /* CHECK IF BLOCK DEVICE REMOTE */ - EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12); + EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12) | (1<<15); ResetCflag; break; case 0x0b: /* SET SHARING RETRY COUNT */ + if (!CX) + { + EAX = (EAX & 0xffff0000) | 0x0001; + SetCflag; + break; + } + sharing_pause = CX; + if (!DX) + sharing_retries = DX; ResetCflag; break; @@ -1191,13 +1336,13 @@ int do_int21(struct sigcontext_struct * context) case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */ case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */ - EAX = (EAX & 0xffff0000) | dup(BX); + AX = dup(BX); ResetCflag; break; case 0x47: /* "CWD" - GET CURRENT DIRECTORY */ GetCurrentDirectory(context); - EAX = (EAX & 0xffff0000) | 0x0100; + AX = 0x0100; /* intlist: many Microsoft products for Windows rely on this */ break; @@ -1212,11 +1357,11 @@ int do_int21(struct sigcontext_struct * context) break; case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */ - exit(EAX & 0xff); + exit(AL); break; case 0x4d: /* GET RETURN CODE */ - EAX = (EAX & 0xffffff00) | NoError; /* normal exit */ + AL = NoError; /* normal exit */ break; case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */ @@ -1229,7 +1374,7 @@ int do_int21(struct sigcontext_struct * context) case 0x52: /* "SYSVARS" - GET LIST OF LISTS */ ES = 0x0; - EBX = (EBX & 0xffff0000); + BX = 0x0; IntBarf(0x21, context); break; @@ -1238,7 +1383,7 @@ int do_int21(struct sigcontext_struct * context) break; case 0x57: /* FILE DATE AND TIME */ - switch (EAX & 0xff) + switch (AL) { case 0x00: GetFileDateTime(context); @@ -1250,10 +1395,10 @@ int do_int21(struct sigcontext_struct * context) break; case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */ - switch (EAX & 0xff) + switch (AL) { case 0x00: - EAX = (EAX & 0xffffff00) | 0x01L; + AL = 0x01L; break; case 0x02: EAX &= 0xff00L; @@ -1273,25 +1418,21 @@ int do_int21(struct sigcontext_struct * context) CreateNewFile(context); break; - case 0x5c: /* "FLOCK" - RECORD LOCKING */ - IntBarf(0x21, context); - break; - case 0x5d: /* NETWORK */ case 0x5e: /* network software not installed */ - EAX = (EAX & 0xfffff00) | NoNetwork; + AL = NoNetwork; SetCflag; break; case 0x5f: /* NETWORK */ - switch (EAX & 0xff) + switch (AL) { case 0x07: /* ENABLE DRIVE */ - if (!DOS_EnableDrive(EDX & 0xff)) + if (!DOS_EnableDrive(DL)) { Error(InvalidDrive, EC_MediaError , EL_Disk); - EAX = (EAX & 0xfffff00) | InvalidDrive; + AL = InvalidDrive; SetCflag; break; } @@ -1301,10 +1442,10 @@ int do_int21(struct sigcontext_struct * context) break; } case 0x08: /* DISABLE DRIVE */ - if (!DOS_DisableDrive(EDX & 0xff)) + if (!DOS_DisableDrive(DL)) { Error(InvalidDrive, EC_MediaError , EL_Disk); - EAX = (EAX & 0xfffff00) | InvalidDrive; + AL = InvalidDrive; SetCflag; break; } @@ -1315,7 +1456,7 @@ int do_int21(struct sigcontext_struct * context) } default: /* network software not installed */ - EAX = (EAX & 0xfffff00) | NoNetwork; + AL = NoNetwork; SetCflag; break; } @@ -1335,11 +1476,10 @@ int do_int21(struct sigcontext_struct * context) break; case 0x66: /* GLOBAL CODE PAGE TABLE */ - switch (EAX & 0xff) - { + switch (AL) { case 0x01: - EBX = CodePage; - EDX = BX; + BX = CodePage; + DX = BX; ResetCflag; break; case 0x02: @@ -1358,7 +1498,7 @@ int do_int21(struct sigcontext_struct * context) break; case 0x69: /* DISK SERIAL NUMBER */ - switch (EAX & 0xff) + switch (AL) { case 0x00: GetDiskSerialNumber(context); diff --git a/miscemu/int25.c b/miscemu/int25.c index 9a9a366aec6..af79ec46e29 100644 --- a/miscemu/int25.c +++ b/miscemu/int25.c @@ -1,5 +1,6 @@ #include #include +#include "registers.h" #include "msdos.h" #include "wine.h" @@ -8,15 +9,14 @@ int do_int25(struct sigcontext_struct *context) BYTE *dataptr = pointer(DS, BX); DWORD begin, length; - if( (ECX & 0xffff) == 0xffff) - { + if (CX == 0xffff) { begin = getdword(dataptr); length = getword(&dataptr[4]); dataptr = (BYTE *) getdword(&dataptr[6]); } else { - begin = EDX & 0xffff; - length = ECX & 0xffff; + begin = DX; + length = CX; } fprintf(stderr, "int25: abs diskread, drive %d, sector %d, " "count %d, buffer %d\n", EAX & 0xff, begin, length, (int) dataptr); diff --git a/miscemu/int26.c b/miscemu/int26.c index 0308d376973..ff145b1cfa5 100644 --- a/miscemu/int26.c +++ b/miscemu/int26.c @@ -1,5 +1,6 @@ #include #include +#include "registers.h" #include "msdos.h" #include "wine.h" @@ -8,15 +9,14 @@ int do_int26(struct sigcontext_struct *context) BYTE *dataptr = pointer(DS, BX); DWORD begin, length; - if( (ECX & 0xffff) == 0xffff) - { + if (CX == 0xffff) { begin = getdword(dataptr); length = getword(&dataptr[4]); dataptr = (BYTE *) getdword(&dataptr[6]); } else { - begin = EDX & 0xffff; - length = ECX & 0xffff; + begin = DX; + length = CX; } fprintf(stderr,"int26: abs diskwrite, drive %d, sector %d, count %d," diff --git a/miscemu/int2f.c b/miscemu/int2f.c index c652bba689a..e1a619531da 100644 --- a/miscemu/int2f.c +++ b/miscemu/int2f.c @@ -1,6 +1,6 @@ #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" int do_int2f_16(struct sigcontext_struct *context); @@ -10,8 +10,8 @@ int do_int2f(struct sigcontext_struct *context) { switch((context->sc_eax >> 8) & 0xff) { - case 0x10: /* share isn't installed */ - EAX = (EAX & 0xffffff00) | 0x01; + case 0x10: /* share is installed */ + EAX = (EAX & 0xffffff00) | 0xff; break; case 0x15: /* mscdex */ diff --git a/miscemu/int31.c b/miscemu/int31.c index 3d4500ce09e..d738772f205 100644 --- a/miscemu/int31.c +++ b/miscemu/int31.c @@ -1,6 +1,6 @@ #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" typedef struct { diff --git a/miscemu/ioports.c b/miscemu/ioports.c index 35560a2c5eb..07d6af3539d 100644 --- a/miscemu/ioports.c +++ b/miscemu/ioports.c @@ -1,7 +1,7 @@ #include #include #include -#include "msdos.h" +#include "registers.h" #include "wine.h" static BYTE cmosaddress; @@ -18,15 +18,14 @@ static BYTE cmosimage[64] = { void inportb(struct sigcontext_struct *context) { - fprintf(stderr, "IO: inb (%x)\n", EDX & 0xffff); + fprintf(stderr, "IO: inb (%x)\n", DX); - switch(EDX & 0xffff) - { + switch(DX) { case 0x70: - EAX = (EAX & 0xffffff00L) | cmosaddress; + AL = cmosaddress; break; case 0x71: - EAX = (EAX & 0xffffff00L) | cmosimage[cmosaddress & 0x3f]; + AL = cmosimage[cmosaddress & 0x3f]; break; default: } @@ -34,22 +33,22 @@ void inportb(struct sigcontext_struct *context) void inport(struct sigcontext_struct *context) { - fprintf(stderr, "IO: in (%x)\n", EDX & 0xffff); + fprintf(stderr, "IO: in (%x)\n", DX); - EAX = (EAX & 0xffff0000L) | 0xffff; + AX = 0xffff; } void outportb(struct sigcontext_struct *context) { - fprintf(stderr, "IO: outb (%x), %x\n", EDX & 0xffff, EAX & 0xff); + fprintf(stderr, "IO: outb (%x), %x\n", DX, AX); switch (EDX & 0xffff) { case 0x70: - cmosaddress = EAX & 0x7f; + cmosaddress = AL & 0x7f; break; case 0x71: - cmosimage[cmosaddress & 0x3f] = EAX & 0xff; + cmosimage[cmosaddress & 0x3f] = AL; break; default: } @@ -57,5 +56,5 @@ void outportb(struct sigcontext_struct *context) void outport(struct sigcontext_struct *context) { - fprintf(stderr, "IO: out (%x), %x\n", EDX & 0xffff, EAX & 0xffff); + fprintf(stderr, "IO: out (%x), %x\n", DX, AX); } diff --git a/objects/bitmap.c b/objects/bitmap.c index b068a2a6beb..cd4f6232e31 100644 --- a/objects/bitmap.c +++ b/objects/bitmap.c @@ -12,6 +12,9 @@ static char Copyright[] = "Copyright Alexandre Julliard, 1993"; #include "gdi.h" #include "bitmap.h" + /* Include OEM bitmaps */ +#include "bitmaps/check_mark" +#include "bitmaps/menu_arrow" /* Handle of the bitmap selected by default in a memory DC */ HBITMAP BITMAP_hbitmapMemDC = 0; @@ -73,6 +76,59 @@ static XImage *BITMAP_BmpToImage( BITMAP * bmp, void * bmpData ) } +/*********************************************************************** + * BITMAP_LoadOEMBitmap + */ +HBITMAP BITMAP_LoadOEMBitmap( WORD id ) +{ + BITMAPOBJ * bmpObjPtr; + HBITMAP hbitmap; + WORD width, height; + char *data; + + switch(id) + { + case OBM_MNARROW: + width = menu_arrow_width; + height = menu_arrow_height; + data = menu_arrow_bits; + break; + + case OBM_CHECK: + width = check_mark_width; + height = check_mark_height; + data = check_mark_bits; + break; + + default: + return 0; + } + + /* Create the BITMAPOBJ */ + if (!(hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC ))) + return 0; + bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_ADDR( hbitmap ); + bmpObjPtr->size.cx = 0; + bmpObjPtr->size.cy = 0; + bmpObjPtr->bitmap.bmType = 0; + bmpObjPtr->bitmap.bmWidth = width; + bmpObjPtr->bitmap.bmHeight = height; + bmpObjPtr->bitmap.bmWidthBytes = (width + 15) / 16 * 2; + bmpObjPtr->bitmap.bmPlanes = 1; + bmpObjPtr->bitmap.bmBitsPixel = 1; + bmpObjPtr->bitmap.bmBits = NULL; + + /* Create the pixmap */ + if (!(bmpObjPtr->pixmap = XCreateBitmapFromData( display, rootWindow, + data, width, height ))) + { + GDI_HEAP_FREE( hbitmap ); + return 0; + } + return hbitmap; +} + + /*********************************************************************** * CreateBitmap (GDI.48) */ diff --git a/objects/dcvalues.c b/objects/dcvalues.c index 33b51ac068d..c1fafaf6644 100644 --- a/objects/dcvalues.c +++ b/objects/dcvalues.c @@ -73,7 +73,7 @@ func_type func_name( HDC hdc ) \ { \ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \ if (!dc) return 0; \ - return dc->w.ret_x | (dc->w.ret_y << 16); \ + return MAKELONG( dc->w.ret_x, dc->w.ret_y << 16 ); \ } #define DC_GET_VAL_EX( func_name, ret_x, ret_y ) \ @@ -127,7 +127,6 @@ DC_SET_MODE( SetStretchBltMode, stretchBltMode, DC_GET_VAL( COLORREF, GetBkColor, backgroundColor ) /* GDI.75 */ DC_GET_VAL( WORD, GetBkMode, backgroundMode ) /* GDI.76 */ DC_GET_X_Y( DWORD, GetCurrentPosition, CursPosX, CursPosY ) /* GDI.78 */ -DC_GET_X_Y( DWORD, GetDCOrg, DCOrgX, DCOrgY ) /* GDI.79 */ DC_GET_VAL( WORD, GetMapMode, MapMode ) /* GDI.81 */ DC_GET_VAL( WORD, GetPolyFillMode, polyFillMode ) /* GDI.84 */ DC_GET_VAL( WORD, GetROP2, ROPmode ) /* GDI.85 */ diff --git a/objects/dib.c b/objects/dib.c index c6d9d4474f3..6042cb278c8 100644 --- a/objects/dib.c +++ b/objects/dib.c @@ -128,6 +128,71 @@ static void DIB_SetImageBits_4( WORD lines, BYTE *bits, WORD width, } } +#define check_xy(x,y) \ + if (x > width) { \ + x = 0; \ + if (lines) \ + lines--; \ + } + +/*********************************************************************** + * DIB_SetImageBits_RLE4 + * + * SetDIBits for a 4-bit deep compressed DIB. + */ +static void DIB_SetImageBits_RLE4( WORD lines, BYTE *bits, WORD width, + WORD *colors, XImage *bmpImage ) +{ + int x = 0, c, length; + BYTE *begin = bits; + + lines--; + while (1) { + length = *bits++; + if (length) { /* encoded */ + c = *bits++; + while (length--) { + XPutPixel(bmpImage, x++, lines, colors[c >> 4]); + check_xy(x, y); + if (length) { + length--; + XPutPixel(bmpImage, x++, lines, colors[c & 0xf]); + check_xy(x, y); + } + } + } else { + length = *bits++; + switch (length) { + case 0: /* eol */ + x = 0; + lines--; + continue; + + case 1: /* eopicture */ + return; + + case 2: /* delta */ + x += *bits++; + lines -= *bits++; + continue; + + default: /* absolute */ + while (length--) { + c = *bits++; + XPutPixel(bmpImage, x++, lines, colors[c >> 4]); + check_xy(x, y); + if (length) { + length--; + XPutPixel(bmpImage, x++, lines, colors[c & 0xf]); + check_xy(x, y); + } + } + if ((bits - begin) & 1) + bits++; + } + } + } +} /*********************************************************************** * DIB_SetImageBits_8 @@ -148,6 +213,62 @@ static void DIB_SetImageBits_8( WORD lines, BYTE *bits, WORD width, } } +/*********************************************************************** + * DIB_SetImageBits_RLE8 + * + * SetDIBits for an 8-bit deep compressed DIB. + */ +static void DIB_SetImageBits_RLE8( WORD lines, BYTE *bits, WORD width, + WORD *colors, XImage *bmpImage ) +{ + int x = 0, i, length; + BYTE *begin = bits; + + lines--; + while (1) { + length = *bits++; + if (length) { /* encoded */ + while (length--) { + XPutPixel(bmpImage, x++, lines, colors[*bits]); + if (x > width) { + x = 0; + if (lines) + lines--; + } + } + bits++; + } else { + length = *bits++; + switch (length) { + case 0: /* eol */ + x = 0; + lines--; + continue; + + case 1: /* eopicture */ + return; + + case 2: /* delta */ + x += *bits++; + lines -= *bits++; + continue; + + default: /* absolute */ + for (i = length; i ; i--) { + XPutPixel(bmpImage, x++, lines, + colors[*bits++]); + if (x > width) { + x = 0; + if (lines) + lines--; + } + } + if ((bits - begin) & 1) + bits++; + } + } + } +} /*********************************************************************** * DIB_SetImageBits_24 @@ -228,11 +349,19 @@ static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits, colorMapping, bmpImage ); break; case 4: - DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth, + if (info->bmiHeader.biCompression) + DIB_SetImageBits_RLE4( lines, bits, info->bmiHeader.biWidth, + colorMapping, bmpImage ); + else + DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth, colorMapping, bmpImage ); break; case 8: - DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth, + if (info->bmiHeader.biCompression) + DIB_SetImageBits_RLE8( lines, bits, info->bmiHeader.biWidth, + colorMapping, bmpImage ); + else + DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth, colorMapping, bmpImage ); break; case 24: diff --git a/objects/metafile.c b/objects/metafile.c index 544e6e48272..fd9c3ae5dff 100644 --- a/objects/metafile.c +++ b/objects/metafile.c @@ -103,8 +103,8 @@ HMETAFILE CloseMetaFile(HDC hdc) mf = (METAFILE *)GlobalLock(dc->w.hMetaFile); mh = (METAHEADER *)GlobalLock(mf->hMetaHdr); - /* Construct the end of metafile record - this is undocumented - * but is created by MS Windows 3.1. + /* Construct the end of metafile record - this is documented + * in SDK Knowledgebase Q99334. */ if (!MF_MetaParam0(dc, META_EOF)) { diff --git a/objects/text.c b/objects/text.c index f8be278eadf..10a6a7511a0 100644 --- a/objects/text.c +++ b/objects/text.c @@ -451,4 +451,15 @@ BOOL ExtTextOut(HDC hDC, short x, short y, WORD wOptions, LPRECT lprect, return FALSE; } +/*********************************************************************** + * GetTabbedTextExtent [USER.197] + */ +DWORD GetTabbedTextExtent(HDC hDC, LPSTR lpString, int nCount, + int nTabPositions, LPINT lpnTabStopPositions) +{ + printf("EMPTY STUB !!! GetTabbedTextExtent(); !\n"); + + return (18 << 16) | (nCount * 18); +} + diff --git a/windows/dc.c b/windows/dc.c index 056329a2195..9c8a274786a 100644 --- a/windows/dc.c +++ b/windows/dc.c @@ -531,6 +531,23 @@ COLORREF SetTextColor( HDC hdc, COLORREF color ) } +/*********************************************************************** + * GetDCOrg (GDI.79) + */ +DWORD GetDCOrg( HDC hdc ) +{ + Window root; + int x, y, w, h, border, depth; + + DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); + if (!dc) return 0; + if (dc->w.flags & DC_MEMORY) return 0; + XGetGeometry( display, dc->u.x.drawable, &root, + &x, &y, &w, &h, &border, &depth ); + return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y ); +} + + /*********************************************************************** * SetDCOrg (GDI.117) */ diff --git a/windows/defdlg.c b/windows/defdlg.c index 8405dc38aaf..2e5607dbdf4 100644 --- a/windows/defdlg.c +++ b/windows/defdlg.c @@ -50,6 +50,14 @@ LONG DefDlgProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam ) case WM_NCDESTROY: + /* Free dialog heap (if created) */ + if (dlgInfo->hDialogHeap) + { + GlobalUnlock(dlgInfo->hDialogHeap); + GlobalFree(dlgInfo->hDialogHeap); + dlgInfo->hDialogHeap = 0; + } + /* Delete font */ if (dlgInfo->hUserFont) { diff --git a/windows/defwnd.c b/windows/defwnd.c index 1adc1e3ec14..12443b104e7 100644 --- a/windows/defwnd.c +++ b/windows/defwnd.c @@ -26,9 +26,6 @@ extern LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam ); extern LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt ); extern LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam ); extern LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos ); /* winpos.c */ -extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */ -extern BOOL ActivateMenuBarFocus(HWND hWnd); /* menu.c */ - /*********************************************************************** @@ -229,13 +226,12 @@ LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam ) return NC_HandleSysCommand( hwnd, wParam, MAKEPOINT(lParam) ); case WM_SYSKEYDOWN: - if (wParam == VK_MENU) ActivateMenuBarFocus(hwnd); - break; + if (wParam == VK_MENU) + SendMessage( hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0L ); + break; + case WM_SYSKEYUP: break; - case WM_MENUCHAR: - MessageBeep(0); - break; case WM_MEASUREITEM: measure = (MEASUREITEMSTRUCT *)lParam; switch(measure->CtlType) { diff --git a/windows/dialog.c b/windows/dialog.c index e91d95a33b0..7b28b2dd13f 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -15,6 +15,8 @@ static char Copyright[] = "Copyright Alexandre Julliard, 1993"; #include "dialog.h" #include "win.h" #include "user.h" +#include "message.h" +#include "heap.h" /* Dialog base units */ @@ -208,6 +210,8 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate, DWORD exStyle = 0; WORD xUnit = xBaseUnit; WORD yUnit = yBaseUnit; + void *dlgHeapBase; + MDESC *dlgHeap; /* Parse dialog template */ @@ -278,15 +282,16 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate, return 0; } - ShowWindow(hwnd, SW_SHOWNORMAL); - UpdateWindow(hwnd); - /* Create control windows */ #ifdef DEBUG_DIALOG printf( " BEGIN\n" ); #endif + wndPtr = WIN_FindWndPtr( hwnd ); + dlgInfo = (DIALOGINFO *)wndPtr->wExtra; + dlgInfo->hDialogHeap = 0; + for (i = 0; i < template.header->nbItems; i++) { DLGCONTROLHEADER * next_header; @@ -303,16 +308,39 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate, printf(" %d, %d, %d, %d, %d, %08x\n", header->id, header->x, header->y, header->cx, header->cy, header->style ); #endif - if ((strcmp(class, "STATIC") == 0) & ((header->style & SS_ICON) == SS_ICON)) { - header->cx = 32; - header->cy = 32; + + if ((strcmp(class, "EDIT") == 0) && + ((header->style & DS_LOCALEDIT) != DS_LOCALEDIT)) { + if (!dlgInfo->hDialogHeap) { + dlgInfo->hDialogHeap = GlobalAlloc(GMEM_FIXED, 0x10000); + if (!dlgInfo->hDialogHeap) { + printf("CreateDialogIndirectParam: Insufficient memory ", + "to create heap for edit control\n"); + continue; + } + dlgHeapBase = GlobalLock(dlgInfo->hDialogHeap); + HEAP_Init(&dlgHeap, dlgHeapBase, 0x10000); } - header->style |= WS_CHILD; - CreateWindowEx( WS_EX_NOPARENTNOTIFY, - class, text, header->style, - header->x * xUnit / 4, header->y * yUnit / 8, - header->cx * xUnit / 4, header->cy * yUnit / 8, - hwnd, header->id, hInst, NULL ); + header->style |= WS_CHILD; + CreateWindowEx( WS_EX_NOPARENTNOTIFY, + class, text, header->style, + header->x * xUnit / 4, header->y * yUnit / 8, + header->cx * xUnit / 4, header->cy * yUnit / 8, + hwnd, header->id, HIWORD((LONG)dlgHeapBase), NULL ); + } + else { + if ((strcmp(class, "STATIC") == 0) & + ((header->style & SS_ICON) == SS_ICON)) { + header->cx = 32; + header->cy = 32; + } + header->style |= WS_CHILD; + CreateWindowEx( WS_EX_NOPARENTNOTIFY, + class, text, header->style, + header->x * xUnit / 4, header->y * yUnit / 8, + header->cx * xUnit / 4, header->cy * yUnit / 8, + hwnd, header->id, hInst, NULL ); + } header = next_header; } @@ -322,8 +350,6 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate, /* Initialise dialog extra data */ - wndPtr = WIN_FindWndPtr( hwnd ); - dlgInfo = (DIALOGINFO *)wndPtr->wExtra; dlgInfo->dlgProc = dlgProc; dlgInfo->hUserFont = hFont; dlgInfo->hMenu = hMenu; @@ -346,7 +372,7 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, LPCSTR dlgTemplate, /*********************************************************************** * DIALOG_DoDialogBox */ -static int DIALOG_DoDialogBox( HWND hwnd ) +static int DIALOG_DoDialogBox( HWND hwnd, HWND owner ) { WND * wndPtr; DIALOGINFO * dlgInfo; @@ -360,7 +386,8 @@ static int DIALOG_DoDialogBox( HWND hwnd ) dlgInfo = (DIALOGINFO *)wndPtr->wExtra; ShowWindow( hwnd, SW_SHOW ); - while (MSG_InternalGetMessage( lpmsg, hwnd, MSGF_DIALOGBOX, TRUE )) + while (MSG_InternalGetMessage( lpmsg, hwnd, owner, MSGF_DIALOGBOX, + PM_REMOVE, TRUE )) { if (!IsDialogMessage( hwnd, lpmsg)) { @@ -399,7 +426,7 @@ int DialogBoxParam( HINSTANCE hInst, LPCSTR dlgTemplate, hInst, dlgTemplate, owner, dlgProc, param ); #endif hwnd = CreateDialogParam( hInst, dlgTemplate, owner, dlgProc, param ); - if (hwnd) return DIALOG_DoDialogBox( hwnd ); + if (hwnd) return DIALOG_DoDialogBox( hwnd, owner ); return -1; } @@ -426,7 +453,7 @@ int DialogBoxIndirectParam( HINSTANCE hInst, HANDLE dlgTemplate, if (!(ptr = GlobalLock( dlgTemplate ))) return -1; hwnd = CreateDialogIndirectParam( hInst, ptr, owner, dlgProc, param ); GlobalUnlock( dlgTemplate ); - if (hwnd) return DIALOG_DoDialogBox( hwnd ); + if (hwnd) return DIALOG_DoDialogBox( hwnd, owner ); return -1; } diff --git a/windows/mdi.c b/windows/mdi.c index 0835c8a8ef5..80dd6d78c58 100644 --- a/windows/mdi.c +++ b/windows/mdi.c @@ -12,10 +12,12 @@ #include "mdi.h" #include "user.h" #include "sysmetrics.h" -#include "menu.h" #define DEBUG_MDI /* */ +extern WORD MENU_DrawMenuBar( HDC hDC, LPRECT lprect, + HMENU hmenu, BOOL suppress_draw ); /* menu.c */ + /********************************************************************** * MDIRecreateMenuList */ @@ -80,7 +82,7 @@ MDICreateChild(WND *w, MDICLIENTINFO *ci, HWND parent, LPMDICREATESTRUCT cs) WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE | cs->style, cs->x, cs->y, cs->cx, cs->cy, parent, (HMENU) 0, - w->hInstance, (LPSTR) cs->lParam); + w->hInstance, (LPSTR) cs); if (hwnd) { @@ -569,9 +571,7 @@ LONG MDIPaintMaximized(HWND hwndFrame, HWND hwndClient, WORD message, rect.right -= SYSMETRICS_CXSIZE; rect.bottom = rect.top + SYSMETRICS_CYMENU; - StdDrawMenuBar(hdc, &rect, (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu), - FALSE); - GlobalUnlock(wndPtr->wIDmenu); + MENU_DrawMenuBar(hdc, &rect, wndPtr->wIDmenu, FALSE); DeleteDC(hdcMem); ReleaseDC(hwndFrame, hdc); diff --git a/windows/message.c b/windows/message.c index dcb8e5c8efe..fdac1359809 100644 --- a/windows/message.c +++ b/windows/message.c @@ -205,7 +205,7 @@ static void MSG_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos ) * the coordinates to client coordinates. * - Send the WM_SETCURSOR message. */ -static BOOL MSG_TranslateMouseMsg( MSG *msg ) +static BOOL MSG_TranslateMouseMsg( MSG *msg, BOOL remove ) { BOOL eatMsg = FALSE; static DWORD lastClickTime = 0; @@ -280,9 +280,12 @@ static BOOL MSG_TranslateMouseMsg( MSG *msg ) case WM_MBUTTONDOWN: msg->message = WM_MBUTTONDBLCLK; break; } - lastClickTime = msg->time; - lastClickMsg = msg->message; - lastClickPos = msg->pt; + if (remove) + { + lastClickTime = msg->time; + lastClickMsg = msg->message; + lastClickPos = msg->pt; + } } /* Build the translated message */ @@ -631,7 +634,7 @@ static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd, if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST)) - if (!MSG_TranslateMouseMsg( msg )) + if (!MSG_TranslateMouseMsg( msg, flags & PM_REMOVE )) { MSG_RemoveMsg( sysMsgQueue, pos ); continue; @@ -690,20 +693,30 @@ static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd, * 'hwnd' must be the handle of the dialog or menu window. * 'code' is the message filter value (MSGF_??? codes). */ -BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, short code, BOOL sendIdle ) +BOOL MSG_InternalGetMessage( LPMSG msg, HWND hwnd, HWND hwndOwner, short code, + WORD flags, BOOL sendIdle ) { - do + for (;;) { if (sendIdle) { - if (MSG_PeekMessage(appMsgQueue, msg, 0, 0, 0, PM_REMOVE, TRUE)) - continue; - /* FIXME: to which window should we send this? */ - /* SendMessage( hwnd, WM_ENTERIDLE, code, (LPARAM)hwnd ); */ + if (!MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, flags, TRUE )) + { + /* No message present -> send ENTERIDLE and wait */ + SendMessage( hwndOwner, WM_ENTERIDLE, code, (LPARAM)hwnd ); + MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, flags, FALSE ); + } } - MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, PM_REMOVE, FALSE ); - } while (CallMsgFilter( msg, code ) != 0); - return (msg->message != WM_QUIT); + else /* Always wait for a message */ + MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, flags, FALSE ); + + if (!CallMsgFilter( msg, code )) return (msg->message != WM_QUIT); + + /* Message filtered -> remove it from the queue */ + /* if it's still there. */ + if (!(flags & PM_REMOVE)) + MSG_PeekMessage( appMsgQueue, msg, 0, 0, 0, PM_REMOVE, TRUE ); + } } diff --git a/windows/nonclient.c b/windows/nonclient.c index c364b029ee6..2bb188e3667 100644 --- a/windows/nonclient.c +++ b/windows/nonclient.c @@ -12,7 +12,6 @@ static char Copyright[] = "Copyright Alexandre Julliard, 1994"; #include "sysmetrics.h" #include "user.h" #include "scroll.h" -#include "menu.h" #include "syscolor.h" static HBITMAP hbitmapClose = 0; @@ -24,11 +23,19 @@ static HBITMAP hbitmapMaximizeD = 0; static HBITMAP hbitmapRestore = 0; static HBITMAP hbitmapRestoreD = 0; +#define SC_ABOUTWINE (SC_SCREENSAVE+1) +extern HINSTANCE hSysRes; +extern BOOL AboutWine_Proc( HWND hDlg, WORD msg, WORD wParam, LONG lParam ); + extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos, POINT *minTrack, POINT *maxTrack ); /* winpos.c */ extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor ); /* cursor.c */ extern WORD MENU_GetMenuBarHeight( HWND hwnd, WORD menubarWidth, int orgX, int orgY ); /* menu.c */ +extern void MENU_TrackMouseMenuBar( HWND hwnd, POINT pt ); /* menu.c */ +extern void MENU_TrackKbdMenuBar( HWND hwnd, WORD wParam ); /* menu.c */ +extern WORD MENU_DrawMenuBar( HDC hDC, LPRECT lprect, + HMENU hmenu, BOOL suppress_draw ); /* menu.c */ /* Some useful macros */ @@ -70,8 +77,8 @@ static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle ) } if ((style & WS_CAPTION) == WS_CAPTION) - rect->top -= SYSMETRICS_CYCAPTION - 1; - if (menu) rect->top -= SYSMETRICS_CYMENU + 1; + rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER; + if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER; if (style & WS_VSCROLL) rect->right += SYSMETRICS_CXVSCROLL; if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL; @@ -237,8 +244,9 @@ static LONG NC_InternalNCHitTest( HWND hwnd, POINT pt ) if (!PtInRect( &rect, pt )) { /* Check system menu */ - if ((wndPtr->dwStyle & WS_SYSMENU) && (pt.x <= SYSMETRICS_CXSIZE)) - return HTSYSMENU; + if (wndPtr->dwStyle & WS_SYSMENU) + rect.left += SYSMETRICS_CXSIZE; + if (pt.x <= rect.left) return HTSYSMENU; /* Check maximize box */ if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1; @@ -311,7 +319,7 @@ LONG NC_HandleNCHitTest( HWND hwnd, POINT pt ) /*********************************************************************** * NC_DrawSysButton */ -static void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down ) +void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down ) { RECT rect; WND *wndPtr = WIN_FindWndPtr( hwnd ); @@ -611,19 +619,17 @@ void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active, BOOL suppress_menupaint ) if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION) { RECT r = rect; - rect.top += SYSMETRICS_CYSIZE + 1; - r.bottom = rect.top - 1; + r.bottom = rect.top + SYSMETRICS_CYSIZE; + rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER; NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active ); } if (HAS_MENU(wndPtr)) { - LPPOPUPMENU lpMenu = (LPPOPUPMENU) GlobalLock( wndPtr->wIDmenu ); RECT r = rect; - r.bottom = rect.top + lpMenu->Height; - rect.top += lpMenu->Height; - StdDrawMenuBar( hdc, &r, lpMenu, suppress_menupaint ); - GlobalUnlock( wndPtr->wIDmenu ); + r.bottom = rect.top + SYSMETRICS_CYMENU; /* default height */ + rect.top += MENU_DrawMenuBar( hdc, &r, (HMENU)wndPtr->wIDmenu, + suppress_menupaint ); } if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL)) { @@ -1111,27 +1117,33 @@ static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT pt ) ReleaseCapture(); } - /*********************************************************************** - * NC_TrackMouseMenuBar + * NC_TrackSysMenu * - * Track a mouse events for the MenuBar. + * Track a mouse button press on the system menu. */ -static void NC_TrackMouseMenuBar( HWND hwnd, WORD wParam, POINT pt ) +static void NC_TrackSysMenu( HWND hwnd, HDC hdc, POINT pt ) { - WND *wndPtr; - LPPOPUPMENU lppop; - MSG msg; - wndPtr = WIN_FindWndPtr(hwnd); - lppop = (LPPOPUPMENU)GlobalLock(wndPtr->wIDmenu); -#ifdef DEBUG_MENU - printf("NC_TrackMouseMenuBar // wndPtr=%08X lppop=%08X !\n", wndPtr, lppop); -#endif - ScreenToClient(hwnd, &pt); - pt.y += lppop->rect.bottom; - SetCapture(hwnd); - MenuButtonDown(hwnd, lppop, pt.x, pt.y); - GlobalUnlock(wndPtr->wIDmenu); + RECT rect; + WND *wndPtr = WIN_FindWndPtr( hwnd ); + + if (!(wndPtr->dwStyle & WS_SYSMENU)) return; + /* If window has a menu, track the menu bar normally */ + if (HAS_MENU(wndPtr)) MENU_TrackMouseMenuBar( hwnd, pt ); + else + { + /* Otherwise track the system menu like a normal popup menu */ + NC_GetInsideRect( hwnd, &rect ); + OffsetRect( &rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top ); + if (wndPtr->dwStyle & WS_CHILD) + ClientToScreen( wndPtr->hwndParent, (POINT *)&rect ); + rect.right = rect.left + SYSMETRICS_CXSIZE; + rect.bottom = rect.top + SYSMETRICS_CYSIZE; + NC_DrawSysButton( hwnd, hdc, TRUE ); + TrackPopupMenu( wndPtr->hSysMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, + rect.left, rect.bottom, 0, hwnd, &rect ); + NC_DrawSysButton( hwnd, hdc, FALSE ); + } } @@ -1151,8 +1163,7 @@ LONG NC_HandleNCLButtonDown( HWND hwnd, WORD wParam, LONG lParam ) break; case HTSYSMENU: - NC_DrawSysButton( hwnd, hdc, TRUE ); - NC_TrackSysMenu(hwnd); + NC_TrackSysMenu( hwnd, hdc, MAKEPOINT(lParam) ); break; case HTMENU: @@ -1263,22 +1274,28 @@ LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt ) break; case SC_MOUSEMENU: - NC_TrackMouseMenuBar( hwnd, wParam, pt ); + MENU_TrackMouseMenuBar( hwnd, pt ); break; case SC_KEYMENU: -/* NC_KeyMenuBar( hwnd, wParam, pt ); */ + MENU_TrackKbdMenuBar( hwnd, wParam ); break; case SC_ARRANGE: break; case SC_TASKLIST: - case SC_SCREENSAVE: + /* WinExec( "taskman.exe", SW_SHOWNORMAL ); */ + break; + case SC_HOTKEY: break; + + case SC_SCREENSAVE: + if (wParam == SC_ABOUTWINE) + DialogBox( hSysRes, MAKEINTRESOURCE(2), + hwnd, (FARPROC)AboutWine_Proc ); + break; } return 0; } - - diff --git a/windows/utility.c b/windows/utility.c index 32f1e59546e..afec60449ed 100644 --- a/windows/utility.c +++ b/windows/utility.c @@ -382,21 +382,14 @@ int wsprintf(LPSTR lpOutput, LPSTR lpFormat, ...) int wvsprintf(LPSTR buf, LPSTR format, LPSTR args) { - char qualified_fmt[1536]; char *newargs; int result; - /* 1.5K is a safe value as wvsprintf can only handle buffers up to - 1K and in a worst case such a buffer would look like "%i%i%i..." */ - if(!buf || !format) return 0; - /* Change the format string so that ints are handled as short by - default */ - /* Convert agruments to 32-bit values */ newargs = UTILITY_convertArgs(format, args); - result = vsprintf(buf, qualified_fmt, newargs); + result = vsprintf(buf, format, newargs); free(newargs); return result; diff --git a/windows/win.c b/windows/win.c index 8aeba56b514..39249089092 100644 --- a/windows/win.c +++ b/windows/win.c @@ -247,6 +247,7 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName, HANDLE class, hwnd; CLASS *classPtr; WND *wndPtr, *parentPtr = NULL; + POINT maxSize, maxPos, minTrack, maxTrack; CREATESTRUCT *createStruct; HANDLE hcreateStruct; int wmcreate; @@ -379,6 +380,19 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName, win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0); + WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack ); + + if ( maxSize.x < width) + { + width = maxSize.x; + wndPtr->rectWindow.right = x + width; + } + if ( maxSize.y < height) + { + height = maxSize.y; + wndPtr->rectWindow.bottom = y + height; + } + wndPtr->window = XCreateWindow( display, parentPtr->window, x + parentPtr->rectClient.left - parentPtr->rectWindow.left, y + parentPtr->rectClient.top - parentPtr->rectWindow.top,