diff --git a/ANNOUNCE b/ANNOUNCE index 662f7c4784c..db46d6a3b1b 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,15 +1,14 @@ -This is release 960302 of Wine the MS Windows emulator. This is still a +This is release 960309 of Wine the MS Windows emulator. This is still a developer's only release. There are many bugs and many unimplemented API features. Most applications still do not work. Patches should be submitted to "julliard@lrc.epfl.ch". Please don't forget to include a ChangeLog entry. -WHAT'S NEW with Wine-960302: (see ChangeLog for details) - - Program manager clone using Winelib. - - Support for Esperanto language. - - Some scrollbar fixes. - - Edit control improvements. +WHAT'S NEW with Wine-960309: (see ChangeLog for details) + - More edit control improvements. + - Help begins to work. + - Internal LZEXPAND.DLL. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -18,10 +17,10 @@ Because of lags created by using mirror, this message may reach you before the release is available at the ftp sites. The sources will be available from the following locations: - sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960302.tar.gz - tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960302.tar.gz - ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960302.tar.gz - aris.com:/pub/linux/ALPHA/Wine/development/Wine-960302.tar.gz + sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960309.tar.gz + tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960309.tar.gz + ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960309.tar.gz + aris.com:/pub/linux/ALPHA/Wine/development/Wine-960309.tar.gz It should also be available from any site that mirrors tsx-11 or sunsite. diff --git a/ChangeLog b/ChangeLog index 3ab435b6b85..3191e3e3fc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,99 @@ +---------------------------------------------------------------------- +Fri Mar 8 19:07:18 1996 Alexandre Julliard + + * [configure.in] + Quote '[' and ']' in the test program for the strength-reduce + bug. This should work much better... + + * [files/file.c] + Augmented DOS_FILE structure. Most internal functions now return a + DOS_FILE* instead of a Unix handle. + Added a local file array to replace the PDB list upon startup, to + allow using file I/O functions before the first task is created. + Added FILE_SetDateTime() and FILE_Sync() functions. + + * [loader/module.c] + Use the DOS file I/O functions in MODULE_LoadExeHeader(). + + * [objects/bitblt.c] + Use visible region instead of GC clip region to clip source + area. This fixes the card drawing bug in freecell. + + * [objects/region.c] + Fixed CombineRgn() to allow src and dest regions to be the same. + +Fri Mar 8 16:32:23 1996 Frans van Dorsselaer + + * [controls/EDIT.TODO] + Updated so it reflects the current status. + + * [controls/edit.c] + Implemented internal EDIT_WordBreakProc(). + Implemented ES_READONLY. + Implemented WM_LBUTTONDBLCLK to select whole words. + Fixed a lot of types in the function definitions. + +Wed Mar 6 19:55:00 1996 Alex Korobka + + * [debugger/info.c] + Added "walk window" command to walk window list. + + * [windows/mdi.c] + Added proper(?) WM_MDISETMENU message handling. + +Wed Mar 6 09:27:12 1996 Martin von Loewis + + * [if1632/callback.c][if1632/relay32.c] + RELAY32_CallWindowProcConvStruct: new function. + + * [win32/struct32.c][win32/Makefile.in][win32/param.c][win32/user32.c] + struct32.c: new file. Moved all structure conversions into that file + PARAM32_POINT32to16,MSG16to32,USER32_RECT32to16: + renamed to STRUCT32_POINT32to16, ... + WIN32_POINT,WIN32_MSG,WIN32_RECT,WIN32_PAINTSTRUCT: renamed to + POINT32, ... + New conversion functions for NCCALCSIZE_PARAMS, WINDOWPOS, + CREATESTRUCT. + + * [include/windows.h][misc/exec.c] + WINHELP, MULTIKEYHELP, HELPWININFO: new structures + WinHelp: Reimplemented. Thanks to Peter Balch + (100710.2566@compuserve.com) for his valuable research. + + * [win32/winprocs.c] + WIN32_CallWindowProcTo16: new function, call in + USER32_DefWindowProcA,... + +Mon Mar 4 23:22:40 1996 Jim Peterson + + * [include/wintypes.h] + Added "#define __export". + + * [programs/progman/main.c] + Added "#include " for definition of HAVE_WINE_CONSTRUCTOR. + + * [rc/parser.h] [rc/parser.l] [rc/parser.y] [rc/winerc.c] + Eliminated shift/reduce conflict in style definition. + Added crude error message support: "stdin:%d: parse error before '%s'". + Implemented string table support to the best of my ability (it works + with LoadString() calls). + + * [windows/nonclient.c] + Fixed bug in NC_DoSizeMove() that made system menu pop up when title + bar of non-iconized window was clicked (checked for iconization). + +Mon Mar 04 20:55:19 1996 Marcus Meissner + + * [if1632/lzexpand.spec] [if1632/relay.c] + [include/lzexpand.h][misc/lzexpand.c] + LZEXPAND.DLL added. + +Sun Mar 03 18:10:22 1996 Albrecht Kleine + + * [windows/win.c] + Prevent usage of invalid HWNDs in WIN_EnumChildWin(), + this prevents too early termination of EnumChildWindows(). + ---------------------------------------------------------------------- Sat Mar 2 18:19:06 1996 Alexandre Julliard diff --git a/RELEASE-NOTES b/RELEASE-NOTES index ee927be04b9..a9acbd23611 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -5,28 +5,7 @@ If you want to contribute code to Wine, read the DEVELOPER-HINTS. The primary source of information to developers is the ChangeLog (next to the source, of course). -1. make: No rule to make target foo/foo.o. Stop. -This frequently happens when a prior attempt to make foo.o failed. -In the current setup, make does not terminate then, but continues and -realises the problem later on. 'make' again and watch the output. Be -sure to analyze the problem before you report it to the newsgroup. - -2. What are these questions in Configure? -- Emulator/Library: You need an emulator when you want to run MS-Win - binaries. You need a library when you want to compile the source code - of a Windows program. -- Language: Wine can present the system menu in multiple languages. Select - one of English, German, or Norwegian here. -- Inter-process communication: Allows setting up a DDE conversation - between different instances of Wine. Only really useful when - building Wine as a library. -- Malloc debugging: When enabled, the mtrace and mcheck GNU libc functions - are called. You might want to set the MALLOC_TRACE environment variable - to a trace file name. If your system supports another way of malloc - debugging, feel free to add it. -- Config file: Sets the Wine environment. See README for details. - -3. BAR.EXE used to work, but does not work anymore +1. BAR.EXE used to work, but does not work anymore Look at the ChangeLog to see what files have been changed. Try to undo the particular patch and go partially back to the previous version. If you have any suspicions, report them to the author or to the newsgroup. diff --git a/configure b/configure index df78b45d21b..2ad34151f2b 100755 --- a/configure +++ b/configure @@ -1473,11 +1473,11 @@ cat > conftest.$ac_ext < @@ -72,7 +79,6 @@ typedef struct int ClientHeight; /* ditto */ char PasswordChar; /* The password character */ EDITWORDBREAKPROC WordBreakProc; - BOOL WeOwnCaret; /* Do we own the caret ? */ int CaretPrepareCount; /* Did we already prepare the caret ? */ BOOL CaretHidden; /* Did we hide the caret during painting ? */ int oldWndCol; /* WndCol before we started painting */ @@ -96,6 +102,7 @@ typedef struct #define IsMultiLine(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE) #define IsVScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL) #define IsHScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL) +#define IsReadOnly(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_READONLY) /* internal variables */ static BOOL TextMarking; /* TRUE if text marking in progress */ @@ -117,7 +124,7 @@ static HLOCAL EDIT_HeapAlloc(HWND hwnd, int bytes, WORD flags) ret = LOCAL_Alloc( WIN_GetWindowInstance(hwnd), flags, bytes ); if (!ret) - printf("EDIT_HeapAlloc: Out of heap-memory\n"); + fprintf(stderr, "EDIT_HeapAlloc: Out of heap-memory\n"); return ret; } @@ -235,7 +242,7 @@ static void EDIT_CaretHide(HWND hwnd) EDITSTATE *es = EDIT_GetEditState(hwnd); if (!es) return; - if (!es->WeOwnCaret) return; + if (!es->HaveFocus) return; if (!es->CaretPrepareCount) return; if (!es->CaretHidden) @@ -260,7 +267,7 @@ static void EDIT_CaretUpdate(HWND hwnd) es->CaretPrepareCount--; if (es->CaretPrepareCount) return; - if (!es->WeOwnCaret) return; + if (!es->HaveFocus) return; if ((es->WndCol != es->oldWndCol) || (es->WndRow != es->oldWndRow)) SetCaretPos(es->WndCol, es->WndRow * es->txtht); @@ -276,15 +283,53 @@ static void EDIT_CaretUpdate(HWND hwnd) * EDIT_WordBreakProc * * Find the beginning of words. + * Note: unlike the specs for a WordBreakProc, this function only + * allows to be called without linebreaks between s[0] upto + * s[count - 1]. Remember it is only called + * internally, so we can decide this for ourselves. */ -static int CALLBACK EDIT_WordBreakProc(char * pch, int ichCurrent, - int cch, int code) +static int EDIT_WordBreakProc(char *s, int index, int count, int action) { - dprintf_edit(stddeb, "EDIT_WordBreakProc: pch=%p, ichCurrent=%d" - ", cch=%d, code=%d\n", pch, ichCurrent, cch, code); + int ret = 0; - dprintf_edit(stddeb, "string=%s\n", pch); - return 0; + dprintf_edit(stddeb, "EDIT_WordBreakProc: s=%p, index=%d" + ", count=%d, action=%d\n", s, index, count, action); + + switch (action) { + case WB_LEFT: + if (!count) break; + if (index) index--; + if (s[index] == ' ') { + while (index && (s[index] == ' ')) index--; + if (index) { + while (index && (s[index] != ' ')) index--; + if (s[index] == ' ') index++; + } + } else { + while (index && (s[index] != ' ')) index--; + if (s[index] == ' ') index++; + } + ret = index; + break; + case WB_RIGHT: + if (!count) break; + if (index) index--; + if (s[index] == ' ') + while ((index < count) && (s[index] == ' ')) index++; + else { + while (s[index] && (s[index] != ' ') && (index < count)) index++; + while ((s[index] == ' ') && (index < count)) index++; + } + ret = index; + break; + case WB_ISDELIMITER: + ret = (s[index] == ' '); + break; + default: + fprintf(stderr, "EDIT_WordBreakProc: unknown action code !\n"); + break; + } + return ret; } /********************************************************************* @@ -1912,7 +1957,7 @@ static void EDIT_KeyTyped(HWND hwnd, short ch) /********************************************************************* * EM_UNDO message function */ -static LONG EDIT_UndoMsg(HWND hwnd) +static LRESULT EDIT_UndoMsg(HWND hwnd) { char *text; EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -1976,7 +2021,7 @@ static void EDIT_SetHandleMsg(HWND hwnd, WPARAM wParam) /********************************************************************* * EM_SETTABSTOPS message function */ -static LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT EDIT_SetTabStopsMsg(HWND hwnd, WPARAM wParam, LPARAM lParam) { EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2000,7 +2045,7 @@ static LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam) /********************************************************************* * EM_GETLINE message function */ -static LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam) +static LRESULT EDIT_GetLineMsg(HWND hwnd, WPARAM wParam, LPARAM lParam) { char *cp; int len = 0; @@ -2032,13 +2077,13 @@ static LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam) dprintf_edit( stddeb, "EDIT_GetLineMsg: %d %d, len %d\n", (int)(WORD)(*buffer), (int)(WORD)(*(char *)buffer), len); lstrcpyn(buffer, cp, len); - return (LONG)len; + return (LRESULT)len; } /********************************************************************* * EM_GETSEL message function */ -static LONG EDIT_GetSelMsg(HWND hwnd) +static LRESULT EDIT_GetSelMsg(HWND hwnd) { int so, eo; EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2046,13 +2091,13 @@ static LONG EDIT_GetSelMsg(HWND hwnd) so = es->textptrs[es->SelBegLine] + es->SelBegCol; eo = es->textptrs[es->SelEndLine] + es->SelEndCol; - return MAKELONG(so, eo); + return (LRESULT)MAKELONG(so, eo); } /********************************************************************* * EM_REPLACESEL message function */ -static void EDIT_ReplaceSel(HWND hwnd, LONG lParam) +static void EDIT_ReplaceSel(HWND hwnd, LPARAM lParam) { EDIT_DeleteSel(hwnd); EDIT_InsertText(hwnd, (char *)PTR_SEG_TO_LIN(lParam), @@ -2064,24 +2109,24 @@ static void EDIT_ReplaceSel(HWND hwnd, LONG lParam) /********************************************************************* * EM_LINEFROMCHAR message function */ -static LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam) +static LRESULT EDIT_LineFromCharMsg(HWND hwnd, WPARAM wParam) { int row, col; EDITSTATE *es = EDIT_GetEditState(hwnd); if (wParam == (WORD)-1) - return (LONG)(es->SelBegLine); + return (LRESULT)(es->SelBegLine); else EDIT_GetLineCol(hwnd, wParam, &row, &col); - return (LONG)row; + return (LRESULT)row; } /********************************************************************* * EM_LINEINDEX message function */ -static LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam) +static LRESULT EDIT_LineIndexMsg(HWND hwnd, WPARAM wParam) { EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2093,7 +2138,7 @@ static LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam) /********************************************************************* * EM_LINELENGTH message function */ -static LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam) +static LRESULT EDIT_LineLengthMsg(HWND hwnd, WPARAM wParam) { int row, col, len; int sbl, sbc, sel, sec; @@ -2142,7 +2187,7 @@ static LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam) /********************************************************************* * EM_SETSEL message function */ -static void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam) +static void EDIT_SetSelMsg(HWND hwnd, WPARAM wParam, LPARAM lParam) { INT so, eo; EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2259,7 +2304,7 @@ static void EDIT_WM_SetFont(HWND hwnd, WPARAM wParam, LPARAM lParam) if (lParam) UpdateWindow(hwnd); EDIT_RecalcSize(hwnd,es); - if (es->WeOwnCaret) + if (es->HaveFocus) { EDIT_CaretHide(hwnd); DestroyCaret(); @@ -2336,7 +2381,7 @@ static BOOL LOCAL_HeapExists(HANDLE ds) /********************************************************************* * WM_NCCREATE */ -static long EDIT_WM_NCCreate(HWND hwnd, LONG lParam) +static long EDIT_WM_NCCreate(HWND hwnd, LPARAM lParam) { CREATESTRUCT *createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam); WND *wndPtr = WIN_FindWndPtr(hwnd); @@ -2361,7 +2406,7 @@ static long EDIT_WM_NCCreate(HWND hwnd, LONG lParam) /* Caret stuff */ es->CaretPrepareCount = 1; es->CaretHidden = FALSE; - es->WeOwnCaret = FALSE; + es->HaveFocus = FALSE; /* * Hack - If there is no local heap then hwnd should be a globalHeap block * and the local heap needs to be initilised to the same size(minus something) @@ -2458,7 +2503,7 @@ static long EDIT_WM_NCCreate(HWND hwnd, LONG lParam) /********************************************************************* * WM_CREATE */ -static long EDIT_WM_Create(HWND hwnd, LONG lParam) +static LRESULT EDIT_WM_Create(HWND hwnd, LPARAM lParam) { HDC hdc; EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2507,7 +2552,7 @@ static long EDIT_WM_Create(HWND hwnd, LONG lParam) /********************************************************************* * WM_VSCROLL */ -static void EDIT_WM_VScroll(HWND hwnd, WORD wParam, LONG lParam) +static void EDIT_WM_VScroll(HWND hwnd, WPARAM wParam, LPARAM lParam) { /* * EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2532,7 +2577,7 @@ static void EDIT_WM_VScroll(HWND hwnd, WORD wParam, LONG lParam) /********************************************************************* * WM_HSCROLL */ -static void EDIT_WM_HScroll(HWND hwnd, WORD wParam, LONG lParam) +static void EDIT_WM_HScroll(HWND hwnd, WPARAM wParam, LPARAM lParam) { /* * EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2548,7 +2593,7 @@ static void EDIT_WM_HScroll(HWND hwnd, WORD wParam, LONG lParam) /********************************************************************* * WM_SIZE */ -static void EDIT_WM_Size(HWND hwnd, WORD wParam, LONG lParam) +static void EDIT_WM_Size(HWND hwnd, WPARAM wParam, LPARAM lParam) { EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2562,7 +2607,7 @@ static void EDIT_WM_Size(HWND hwnd, WORD wParam, LONG lParam) /********************************************************************* * WM_LBUTTONDOWN */ -static void EDIT_WM_LButtonDown(HWND hwnd, WORD wParam, LONG lParam) +static void EDIT_WM_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam) { char *cp; int len; @@ -2605,7 +2650,7 @@ static void EDIT_WM_LButtonDown(HWND hwnd, WORD wParam, LONG lParam) /********************************************************************* * WM_MOUSEMOVE */ -static void EDIT_WM_MouseMove(HWND hwnd, WORD wParam, LONG lParam) +static void EDIT_WM_MouseMove(HWND hwnd, WPARAM wParam, LPARAM lParam) { /* * EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2625,7 +2670,7 @@ static void EDIT_WM_MouseMove(HWND hwnd, WORD wParam, LONG lParam) /********************************************************************* * WM_CHAR */ -static void EDIT_WM_Char(HWND hwnd, WORD wParam) +static void EDIT_WM_Char(HWND hwnd, WPARAM wParam) { dprintf_edit(stddeb,"EDIT_WM_Char: wParam=%c\n", (char)wParam); @@ -2635,17 +2680,25 @@ static void EDIT_WM_Char(HWND hwnd, WORD wParam) case '\n': if (!IsMultiLine(hwnd)) break; + if (IsReadOnly(hwnd)) + { + EDIT_Home(hwnd); + EDIT_Downward(hwnd); + break; + } wParam = '\n'; EDIT_KeyTyped(hwnd, wParam); break; case VK_TAB: + if (IsReadOnly(hwnd)) break; if (!IsMultiLine(hwnd)) break; EDIT_KeyTyped(hwnd, wParam); break; default: + if (IsReadOnly(hwnd)) break; if (wParam >= 20 && wParam <= 254 && wParam != 127 ) EDIT_KeyTyped(hwnd, wParam); break; @@ -2655,7 +2708,7 @@ static void EDIT_WM_Char(HWND hwnd, WORD wParam) /********************************************************************* * WM_KEYDOWN */ -static void EDIT_WM_KeyDown(HWND hwnd, WORD wParam) +static void EDIT_WM_KeyDown(HWND hwnd, WPARAM wParam) { EDITSTATE *es = EDIT_GetEditState(hwnd); BOOL motionKey = FALSE; @@ -2717,6 +2770,7 @@ static void EDIT_WM_KeyDown(HWND hwnd, WORD wParam) break; case VK_BACK: + if (IsReadOnly(hwnd)) break; if (SelMarked(es)) EDIT_DeleteSel(hwnd); else @@ -2729,6 +2783,7 @@ static void EDIT_WM_KeyDown(HWND hwnd, WORD wParam) break; case VK_DELETE: + if (IsReadOnly(hwnd)) break; if (SelMarked(es)) EDIT_DeleteSel(hwnd); else @@ -2758,7 +2813,7 @@ static void EDIT_WM_KeyDown(HWND hwnd, WORD wParam) /********************************************************************* * WM_SETTEXT */ -static LONG EDIT_WM_SetText(HWND hwnd, LONG lParam) +static LRESULT EDIT_WM_SetText(HWND hwnd, LPARAM lParam) { int len; char *text,*settext; @@ -2789,12 +2844,35 @@ static LONG EDIT_WM_SetText(HWND hwnd, LONG lParam) return EN_ERRSPACE; } +/********************************************************************* + * WM_LBUTTONDBLCLK + */ +static void EDIT_WM_LButtonDblClk(HWND hwnd) +{ + EDITSTATE *es = EDIT_GetEditState(hwnd); + + dprintf_edit(stddeb, "WM_LBUTTONDBLCLK: hwnd=%d\n", hwnd); + if (SelMarked(es)) EDIT_ClearSel(hwnd); + es->SelBegLine = es->SelEndLine = es->CurrLine; + es->SelBegCol = EDIT_CallWordBreakProc(hwnd, + EDIT_TextLine(hwnd, es->CurrLine), + es->CurrCol, + EDIT_LineLength(hwnd, es->CurrLine), + WB_LEFT); + es->SelEndCol = EDIT_CallWordBreakProc(hwnd, + EDIT_TextLine(hwnd, es->CurrLine), + es->CurrCol, + EDIT_LineLength(hwnd, es->CurrLine), + WB_RIGHT); + EDIT_WriteTextLine(hwnd, NULL, es->CurrLine); +} + /********************************************************************* * EditWndProc() */ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - LONG lResult = 0; + LRESULT lResult = 0; char *textPtr; int len; EDITSTATE *es = EDIT_GetEditState(hwnd); @@ -2803,7 +2881,7 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch (uMsg) { case EM_CANUNDO: - lResult = (LONG)es->hDeletedText; + lResult = (LRESULT)es->hDeletedText; break; case EM_EMPTYUNDOBUFFER: @@ -2823,21 +2901,17 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case EM_GETHANDLE: - lResult = (LONG)es->hText; + lResult = (LRESULT)es->hText; break; case EM_GETLINE: if (IsMultiLine(hwnd)) lResult = EDIT_GetLineMsg(hwnd, wParam, lParam); - else - lResult = 0L; break; case EM_GETLINECOUNT: if (IsMultiLine(hwnd)) lResult = es->wlines; - else - lResult = 0L; break; case EM_GETMODIFY: @@ -2858,7 +2932,7 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case EM_GETWORDBREAKPROC: dprintf_edit(stddeb, "EM_GETWORDBREAKPROC\n"); - lResult = (LONG)es->WordBreakProc; + lResult = (LRESULT)es->WordBreakProc; break; case EM_LIMITTEXT: @@ -2877,8 +2951,6 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case EM_LINEINDEX: if (IsMultiLine(hwnd)) lResult = EDIT_LineIndexMsg(hwnd, wParam); - else - lResult = 0L; break; case EM_LINELENGTH: @@ -2907,7 +2979,10 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case EM_SETREADONLY: - fprintf(stdnimp,"edit: cannot process EM_SETREADONLY message\n"); + dprintf_edit(stddeb, "EM_SETREADONLY, wParam=%d\n", wParam); + SetWindowLong(hwnd, GWL_STYLE, + (BOOL)wParam ? (GetWindowLong(hwnd, GWL_STYLE) | ES_READONLY) + : (GetWindowLong(hwnd, GWL_STYLE) & ~(DWORD)ES_READONLY)); break; case EM_SETRECT: @@ -2973,16 +3048,14 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if ((int)wParam > len) { strcpy((char *)PTR_SEG_TO_LIN(lParam), textPtr); - lResult = (DWORD)len ; + lResult = (LRESULT)len ; } - else - lResult = 0L; EDIT_HeapUnlock(hwnd, es->hText); break; case WM_GETTEXTLENGTH: textPtr = EDIT_HeapLock(hwnd, es->hText); - lResult = (DWORD)strlen(textPtr); + lResult = (LRESULT)strlen(textPtr); EDIT_HeapUnlock(hwnd, es->hText); break; @@ -2998,7 +3071,6 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) dprintf_edit(stddeb, "WM_KILLFOCUS\n"); es->HaveFocus = FALSE; DestroyCaret(); - es->WeOwnCaret = FALSE; if (SelMarked(es)) if(GetWindowLong(hwnd,GWL_STYLE) & ES_NOHIDESEL) EDIT_UpdateSel(hwnd); @@ -3026,7 +3098,6 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case WM_MOVE: - lResult = 0; break; case WM_NCCREATE: @@ -3046,7 +3117,6 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) es->HaveFocus = TRUE; if (SelMarked(es)) EDIT_UpdateSel(hwnd); CreateCaret(hwnd, 0, 2, es->txtht); - es->WeOwnCaret = TRUE; SetCaretPos(es->WndCol, es->WndRow * es->txtht); es->CaretHidden = TRUE; NOTIFY_PARENT(hwnd, EN_SETFOCUS); @@ -3059,7 +3129,6 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SETREDRAW: dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n", hwnd, wParam); - lResult = 0; break; #endif case WM_SETTEXT: @@ -3069,7 +3138,6 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SIZE: EDIT_WM_Size(hwnd, wParam, lParam); - lResult = 0; break; case WM_VSCROLL: @@ -3077,9 +3145,7 @@ LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case WM_LBUTTONDBLCLK: - dprintf_edit(stddeb, "WM_LBUTTONDBLCLK: hwnd=%d, wParam=%x\n", - hwnd, wParam); - lResult = 0; + EDIT_WM_LButtonDblClk(hwnd); break; default: diff --git a/controls/scroll.c b/controls/scroll.c index e746ec5b09f..8f67f09e8bc 100644 --- a/controls/scroll.c +++ b/controls/scroll.c @@ -435,7 +435,7 @@ static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, int nBar, RECT *rect, InflateRect( &r, -1, -1 ); GRAPH_DrawReliefRect( hdc, &r, 1, 2, FALSE ); if ((hwndTracking == hwnd) && (nBarTracking == nBar)) - SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize, uTrackingPos); + SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, uTrackingPos); } diff --git a/debugger/dbg.y b/debugger/dbg.y index d42eac74288..1105e0ad12a 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -34,7 +34,8 @@ int yyerror(char *); } %token CONT STEP LIST NEXT QUIT HELP BACKTRACE INFO STACK SEGMENTS REGS -%token ENABLE DISABLE BREAK DELETE SET MODE PRINT EXAM DEFINE ABORT +%token ENABLE DISABLE BREAK DELETE SET MODE PRINT EXAM DEFINE ABORT WALK +%token WND QUEUE %token NO_SYMBOL EOL %token SYMBOLFILE @@ -93,6 +94,8 @@ int yyerror(char *); } | DELETE BREAK NUM EOL { DEBUG_DelBreakpoint( $3 ); } | BACKTRACE EOL { DEBUG_BackTrace(); } + | WALK WND EOL { DEBUG_InitWalk(); DEBUG_WndWalk( NULL ); } + | WALK WND NUM EOL { DEBUG_InitWalk(); DEBUG_WndWalk( $3 ); } | infocmd | x_command | print_command @@ -180,6 +183,8 @@ x_command: | INFO BREAK EOL { DEBUG_InfoBreakpoints(); } | INFO SEGMENTS EOL { LDT_Print( 0, -1 ); } | INFO SEGMENTS expr EOL { LDT_Print( SELECTOR_TO_ENTRY($3), 1 ); } + | INFO WND expr EOL { DEBUG_WndDump( $3 ); } + | INFO QUEUE expr EOL { DEBUG_QueueDump( $3 ); } %% diff --git a/debugger/debug.l b/debugger/debug.l index 50c66d73d48..cc46238ff42 100644 --- a/debugger/debug.l +++ b/debugger/debug.l @@ -90,6 +90,9 @@ enable|enabl|enab|ena { return ENABLE;} disable|disabl|disab|disa|dis { return DISABLE; } delete|delet|dele|del { return DELETE; } quit|qui|qu|q { return QUIT; } +walk|w { return WALK; } +queue|queu|que { return QUEUE; } +window|windo|wind|win|wnd { return WND; } x { return EXAM; } help|hel|he|"?" { return HELP; } diff --git a/debugger/info.c b/debugger/info.c index 54d5140b63a..c17efaaed11 100644 --- a/debugger/info.c +++ b/debugger/info.c @@ -7,8 +7,190 @@ #include #include +#include "global.h" +#include "user.h" +#include "class.h" +#include "win.h" +#include "message.h" +#include "spy.h" #include "debugger.h" +int iWndIndent = 0; + +extern char lpstrSpyMessageIndent[]; /* from misc/spy.c */ + +/*********************************************************************** + * DEBUG_InitWalk + */ +void DEBUG_InitWalk(void) +{ + fprintf(stderr,"%-24.24s %-6.6s %-17.17s %-8.8s %s\n", + "HWND / WNDPTR","hQueue","Class Name", "Style", "WndProc"); + lpstrSpyMessageIndent[0]='\0'; +} + +/*********************************************************************** + * DEBUG_WndWalk + * + */ +void DEBUG_WndWalk(HWND hStart) +{ + WND* wndPtr; + CLASS* classPtr; + char className[0x10]; + int i; + + if( !hStart ) + hStart = GetDesktopHwnd(); + + wndPtr = WIN_FindWndPtr(hStart); + + if( !wndPtr ) + { fprintf(stderr, "Invalid window handle: %04x\n", hStart); + return; } + + i = strlen(lpstrSpyMessageIndent); + + /* 0x10 bytes are always reserved at the end of lpstrSpyMessageIndent */ + sprintf(lpstrSpyMessageIndent + i,"%04x %08x",hStart, (unsigned) wndPtr); + + classPtr = CLASS_FindClassPtr(wndPtr->hClass); + if(classPtr) + GlobalGetAtomName(classPtr->atomName ,className, 0x10); + else + strcpy(className,""); + + fprintf(stderr,"%-24.24s %-6.4x %-17.17s %08x %04x:%04x\n", + lpstrSpyMessageIndent, + wndPtr->hmemTaskQ, + className, + (unsigned) wndPtr->dwStyle, + HIWORD(wndPtr->lpfnWndProc), + LOWORD(wndPtr->lpfnWndProc)); + + lpstrSpyMessageIndent[i] = '\0'; + + if( wndPtr->hwndChild ) + { + /* walk children */ + + hStart = wndPtr->hwndChild; + wndPtr = WIN_FindWndPtr(hStart); + + iWndIndent ++; + if( iWndIndent < SPY_MAX_INDENTLEVEL - 0x10 ) + { + lpstrSpyMessageIndent[iWndIndent - 1] = ' '; + lpstrSpyMessageIndent[iWndIndent] = '\0'; + } + + while( wndPtr ) + { + DEBUG_WndWalk(hStart); + hStart = wndPtr->hwndNext; + wndPtr = WIN_FindWndPtr(hStart); + } + + if( hStart ) + fprintf(stderr, "%s%s"NPFMT"\n", lpstrSpyMessageIndent, + "", hStart); + + if( iWndIndent ) + { + iWndIndent--; + if( iWndIndent < SPY_MAX_INDENTLEVEL - 0x10 ) + lpstrSpyMessageIndent[iWndIndent] = '\0'; + } + + } +} + +/*********************************************************************** + * DEBUG_WndDump + * + */ +void DEBUG_WndDump(HWND hWnd) +{ + WND* wnd; + char* lpWndText = NULL; + + wnd = WIN_FindWndPtr(hWnd); + + if( !wnd ) + { fprintf(stderr, "Invalid window handle: %04x\n", hWnd); + return; } + + if( wnd->hText ) + lpWndText = (LPSTR) USER_HEAP_LIN_ADDR( wnd->hText ); + + fprintf( stderr, "next: %12.4x\n" + "child: %10.4x\n" + "parent: %10.4x\n" + "owner: %10.4x\n" + "hClass: %10.4x\n" + "hInst: %10.4x\n" + "clientRect: %i,%i - %i,%i\n" + "windowRect: %i,%i - %i,%i\n" + "hRgnUpdate: %6.4x\n" + "hLastPopup: %6.4x\n" + "Style: %10.8x\n" + "StyleEx: %9.8x\n" + "hDCE: %10.4x\n" + "hVscroll: %8.4x\n" + "hHscroll: %8.4x\n" + "menuID: %10.4x\n" + "hText: %10.4x (\"%s\")\n" + "flags: %10.4x\n", + wnd->hwndNext, wnd->hwndChild,wnd->hwndParent, + wnd->hwndOwner,wnd->hClass,wnd->hInstance, + wnd->rectClient.left, wnd->rectClient.top, + wnd->rectClient.right, wnd->rectClient.bottom, + wnd->rectWindow.left, wnd->rectWindow.top, + wnd->rectWindow.right, wnd->rectWindow.bottom, + wnd->hrgnUpdate, wnd->hwndLastActive, + (unsigned) wnd->dwStyle, (unsigned) wnd->dwExStyle, + wnd->hdce, wnd->hVScroll, wnd->hHScroll, + wnd->wIDmenu, wnd->hText, (lpWndText)?lpWndText:"NULL", + wnd->flags); +} + +/*********************************************************************** + * DEBUG_QueueDump + * + */ +void DEBUG_QueueDump(HQUEUE hQ) +{ + MESSAGEQUEUE* pq; + + if( !hQ || IsBadReadPtr((SEGPTR)MAKELONG( 0, GlobalHandleToSel(hQ)), + sizeof(MESSAGEQUEUE)) ) + { + fprintf(stderr, "Invalid queue handle: "NPFMT"\n", hQ); + return; + } + + pq = (MESSAGEQUEUE*) GlobalLock( hQ ); + + fprintf(stderr,"next: %12.4x Intertask SendMessage:\n" + "hTask: %11.4x ----------------------\n" + "msgSize: %9.4x hWnd: %10.4x\n" + "msgCount: %8.4x msg: %11.4x\n" + "msgNext: %9.4x wParam: %8.4x\n" + "msgFree: %9.4x lParam: %8.8x\n" + "qSize: %11.4x lRet: %10.8x\n" + "wWinVer: %9.4x ISMH: %10.4x\n" + "paints: %10.4x hSendTask: %5.4x\n" + "timers: %10.4x hPrevSend: %5.4x\n" + "wakeBits: %8.4x\n" + "wakeMask: %8.4x\n" + "hCurHook: %8.4x\n", + pq->next, pq->hTask, pq->msgSize, pq->hWnd, + pq->msgCount, pq->msg, pq->nextMessage, pq->wParam, + pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize, + (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle, + pq->wPaintCount, pq->hSendingTask, pq->wTimerCount, + pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook); +} /*********************************************************************** * DEBUG_Print @@ -108,8 +290,10 @@ void DEBUG_Help(void) " step next", " mode [16,32] print ", " set = set * = ", +" walk [wnd] dump [wnd, queue] ", " info [reg,stack,break,segments] bt", " symbolfile define ", +" list ", "", "The 'x' command accepts repeat counts and formats (including 'i') in the", "same way that gdb does.", @@ -143,7 +327,7 @@ void DEBUG_List( DBG_ADDR *addr, int count ) { DEBUG_PrintAddress( addr, dbg_mode ); fprintf( stderr, ": " ); - if (!DBG_CHECK_READ_PTR( addr, 1 )) break; + if (!DBG_CHECK_READ_PTR( addr, 1 )) return; DEBUG_Disasm( addr ); fprintf (stderr, "\n"); } diff --git a/files/dos_fs.c b/files/dos_fs.c index e0172f6af89..2b736ca56a2 100644 --- a/files/dos_fs.c +++ b/files/dos_fs.c @@ -259,9 +259,9 @@ static int DOSFS_Match( const char *mask, const char *name ) * * Convert a Unix time in the DOS date/time format. */ -void DOSFS_ToDosDateTime( time_t *unixtime, WORD *pDate, WORD *pTime ) +void DOSFS_ToDosDateTime( time_t unixtime, WORD *pDate, WORD *pTime ) { - struct tm *tm = localtime( unixtime ); + struct tm *tm = localtime( &unixtime ); if (pTime) *pTime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2); if (pDate) @@ -652,12 +652,11 @@ int DOSFS_FindNext( const char *path, const char *mask, int drive, if ((attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL) { - time_t now = time(NULL); if (skip) return 0; strcpy( entry->name, DRIVE_GetLabel( drive ) ); entry->attr = FA_LABEL; entry->size = 0; - DOSFS_ToDosDateTime( &now, &entry->date, &entry->time ); + DOSFS_ToDosDateTime( time(NULL), &entry->date, &entry->time ); return 1; } diff --git a/files/file.c b/files/file.c index 8ea3d1e9f52..a16f929c33b 100644 --- a/files/file.c +++ b/files/file.c @@ -8,11 +8,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "windows.h" #include "directory.h" @@ -25,91 +27,115 @@ #include "task.h" #include "stddebug.h" #include "debug.h" +#include "xmalloc.h" #define MAX_OPEN_FILES 64 /* Max. open files for all tasks; must be <255 */ -typedef struct +typedef struct tagDOS_FILE { - int unix_handle; - int mode; + struct tagDOS_FILE *next; + int count; /* Usage count (0 if free) */ + int unix_handle; + int mode; + char *unix_name; + WORD filedate; + WORD filetime; } DOS_FILE; /* Global files array */ -static DOS_FILE DOSFiles[MAX_OPEN_FILES]; +static DOS_FILE DOSFiles[MAX_OPEN_FILES] = { { 0, }, }; +static DOS_FILE *FILE_First = DOSFiles; +static DOS_FILE *FILE_LastUsed = DOSFiles; + +/* Small file handles array for boot-up, before the first PDB is created */ +#define MAX_BOOT_HANDLES 4 +static BYTE bootFileHandles[MAX_BOOT_HANDLES] = { 0xff, 0xff, 0xff, 0xff }; /*********************************************************************** - * FILE_AllocDOSFile + * FILE_Alloc * - * Allocate a file from the DOS files array. + * Allocate a DOS file. */ -static BYTE FILE_AllocDOSFile( int unix_handle ) +static DOS_FILE *FILE_Alloc(void) { - BYTE i; - for (i = 0; i < MAX_OPEN_FILES; i++) if (!DOSFiles[i].mode) + DOS_FILE *file = FILE_First; + if (file) FILE_First = file->next; + else if (FILE_LastUsed >= &DOSFiles[MAX_OPEN_FILES-1]) { - DOSFiles[i].unix_handle = unix_handle; - DOSFiles[i].mode = 1; - return i; + DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk ); + return NULL; } - return 0xff; + else file = ++FILE_LastUsed; + file->count = 1; + file->unix_handle = -1; + file->unix_name = NULL; + return file; } /*********************************************************************** - * FILE_FreeDOSFile + * FILE_Close * - * Free a file from the DOS files array. + * Close a DOS file. */ -static BOOL FILE_FreeDOSFile( BYTE handle ) +static BOOL FILE_Close( DOS_FILE *file ) { - if (handle >= MAX_OPEN_FILES) return FALSE; - if (!DOSFiles[handle].mode) return FALSE; - DOSFiles[handle].mode = 0; + if (!file->count) return FALSE; + if (--file->count > 0) return TRUE; + /* Now really close the file */ + if (file->unix_handle != -1) close( file->unix_handle ); + if (file->unix_name) free( file->unix_name ); + file->next = FILE_First; + FILE_First = file; return TRUE; } /*********************************************************************** - * FILE_GetUnixHandle + * FILE_GetPDBFiles * - * Return the Unix handle for a global DOS file handle. + * Return a pointer to the current PDB files array. */ -static int FILE_GetUnixHandle( BYTE handle ) +static void FILE_GetPDBFiles( BYTE **files, WORD *nbFiles ) { - if (handle >= MAX_OPEN_FILES) return -1; - if (!DOSFiles[handle].mode) return -1; - return DOSFiles[handle].unix_handle; + PDB *pdb; + + if ((pdb = (PDB *)GlobalLock( GetCurrentPDB() )) != NULL) + { + *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + *nbFiles = pdb->nbFiles; + } + else + { + *files = bootFileHandles; + *nbFiles = MAX_BOOT_HANDLES; + } } /*********************************************************************** * FILE_AllocTaskHandle * - * Allocate a per-task file handle. + * Allocate a task file handle for a DOS file. */ -static HFILE FILE_AllocTaskHandle( int unix_handle ) +static HFILE FILE_AllocTaskHandle( DOS_FILE *dos_file ) { - PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); BYTE *files, *fp; - WORD i; + WORD i, nbFiles; - if (!pdb) - { - fprintf(stderr,"FILE_MakeTaskHandle: internal error, no current PDB.\n"); - exit(1); - } - files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + FILE_GetPDBFiles( &files, &nbFiles ); fp = files + 1; /* Don't use handle 0, as some programs don't like it */ - for (i = pdb->nbFiles - 1; (i > 0) && (*fp != 0xff); i--, fp++); - if (!i || (*fp = FILE_AllocDOSFile( unix_handle )) == 0xff) + for (i = nbFiles - 1; (i > 0) && (*fp != 0xff); i--, fp++); + if (!i) { /* No more handles or files */ DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk ); return -1; } + *fp = dos_file ? (BYTE)(dos_file - DOSFiles) : 0; dprintf_file(stddeb, - "FILE_AllocTaskHandle: returning task handle %d, file %d for unix handle %d file %d of %d \n", - (fp - files), *fp, unix_handle, pdb->nbFiles - i, pdb->nbFiles ); + "FILE_AllocTaskHandle: returning task handle %d, dos_file %d, file %d of %d \n", + (fp - files), *fp, nbFiles - i, nbFiles ); return (HFILE)(fp - files); } @@ -121,19 +147,13 @@ static HFILE FILE_AllocTaskHandle( int unix_handle ) */ static void FILE_FreeTaskHandle( HFILE handle ) { - PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); BYTE *files; - - if (!pdb) - { - fprintf(stderr,"FILE_FreeTaskHandle: internal error, no current PDB.\n"); - exit(1); - } - files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + WORD nbFiles; + + FILE_GetPDBFiles( &files, &nbFiles ); dprintf_file( stddeb,"FILE_FreeTaskHandle: dos=%d file=%d\n", handle, files[handle] ); - if ((handle < 0) || (handle >= (INT)pdb->nbFiles) || - !FILE_FreeDOSFile( files[handle] )) + if ((handle < 0) || (handle >= (INT)nbFiles)) { fprintf( stderr, "FILE_FreeTaskHandle: invalid file handle %d\n", handle ); @@ -144,29 +164,49 @@ static void FILE_FreeTaskHandle( HFILE handle ) /*********************************************************************** - * FILE_GetUnixTaskHandle + * FILE_SetTaskHandle * - * Return the Unix file handle associated to a task file handle. + * Set the value of a task handle (no error checking). */ -int FILE_GetUnixTaskHandle( HFILE handle ) +static void FILE_SetTaskHandle( HFILE handle, DOS_FILE *file ) { - PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); BYTE *files; - int unix_handle; + WORD nbFiles; - if (!pdb) - { - fprintf(stderr,"FILE_GetUnixHandle: internal error, no current PDB.\n"); - exit(1); - } - files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); - if ((handle < 0) || (handle >= (INT)pdb->nbFiles) || - ((unix_handle = FILE_GetUnixHandle( files[handle] )) == -1)) + FILE_GetPDBFiles( &files, &nbFiles ); + files[handle] = (BYTE)(file - DOSFiles); +} + + +/*********************************************************************** + * FILE_GetFile + * + * Return the DOS file associated to a task file handle. + */ +static DOS_FILE *FILE_GetFile( HFILE handle ) +{ + BYTE *files; + WORD nbFiles; + DOS_FILE *file; + + FILE_GetPDBFiles( &files, &nbFiles ); + if ((handle < 0) || (handle >= (INT)nbFiles) || + (files[handle] >= MAX_OPEN_FILES) || + !(file = &DOSFiles[files[handle]])->count) { DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk ); - return -1; + return NULL; } - return unix_handle; + return file; +} + + +int FILE_GetUnixHandle( HFILE hFile ) +{ + DOS_FILE *file; + + if (!(file = FILE_GetFile( hFile ))) return -1; + return file->unix_handle; } @@ -180,22 +220,14 @@ void FILE_CloseAllFiles( HANDLE hPDB ) BYTE *files; WORD count; PDB *pdb = (PDB *)GlobalLock( hPDB ); - int unix_handle; if (!pdb) return; files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); dprintf_file(stddeb,"FILE_CloseAllFiles: closing %d files\n",pdb->nbFiles); for (count = pdb->nbFiles; count > 0; count--, files++) { - if (*files != 0xff) - { - if ((unix_handle = FILE_GetUnixHandle( *files )) != -1) - { - close( unix_handle ); - FILE_FreeDOSFile( *files ); - } - *files = 0xff; - } + if (*files < MAX_OPEN_FILES) FILE_Close( &DOSFiles[*files] ); + *files = 0xff; } } @@ -251,42 +283,45 @@ void FILE_SetDosError(void) /*********************************************************************** * FILE_OpenUnixFile */ -static int FILE_OpenUnixFile( const char *name, int mode ) +static DOS_FILE *FILE_OpenUnixFile( const char *name, int mode ) { - int handle; + DOS_FILE *file; struct stat st; - if ((handle = open( name, mode )) == -1) + if (!(file = FILE_Alloc())) return NULL; + if ((file->unix_handle = open( name, mode )) == -1) { if (Options.allowReadOnly && (mode == O_RDWR)) { - if ((handle = open( name, O_RDONLY )) != -1) + if ((file->unix_handle = open( name, O_RDONLY )) != -1) fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", name ); } } - if (handle != -1) /* Make sure it's not a directory */ + if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1)) { - if ((fstat( handle, &st ) == -1)) - { - FILE_SetDosError(); - close( handle ); - handle = -1; - } - else if (S_ISDIR(st.st_mode)) - { - DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk ); - close( handle ); - handle = -1; - } + FILE_SetDosError(); + FILE_Close( file ); + return NULL; } - return handle; + if (S_ISDIR(st.st_mode)) + { + DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk ); + FILE_Close( file ); + return NULL; + } + + /* File opened OK, now fill the DOS_FILE */ + + file->unix_name = xstrdup( name ); + DOSFS_ToDosDateTime( st.st_mtime, &file->filedate, &file->filetime ); + return file; } /*********************************************************************** * FILE_Open */ -int FILE_Open( LPCSTR path, int mode ) +static DOS_FILE *FILE_Open( LPCSTR path, int mode ) { const char *unixName; @@ -298,10 +333,10 @@ int FILE_Open( LPCSTR path, int mode ) { dprintf_file(stddeb, "FILE_Open: Non-existing device\n"); DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); - return -1; + return NULL; } } - else if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return -1; + else if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return NULL; return FILE_OpenUnixFile( unixName, mode ); } @@ -309,10 +344,10 @@ int FILE_Open( LPCSTR path, int mode ) /*********************************************************************** * FILE_Create */ -int FILE_Create( LPCSTR path, int mode, int unique ) +static DOS_FILE *FILE_Create( LPCSTR path, int mode, int unique ) { + DOS_FILE *file; const char *unixName; - int handle; dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique ); @@ -320,15 +355,30 @@ int FILE_Create( LPCSTR path, int mode, int unique ) { dprintf_file(stddeb, "FILE_Create: creating device '%s'!\n", unixName); DOS_ERROR( ER_AccessDenied, EC_NotFound, SA_Abort, EL_Disk ); - return -1; + return NULL; } - if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return -1; - if ((handle = open( unixName, - O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0), - mode )) == -1) + if (!(file = FILE_Alloc())) return NULL; + + if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) + { + FILE_Close( file ); + return NULL; + } + if ((file->unix_handle = open( unixName, + O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0), + mode )) == -1) + { FILE_SetDosError(); - return handle; + FILE_Close( file ); + return NULL; + } + + /* File created OK, now fill the DOS_FILE */ + + file->unix_name = xstrdup( unixName ); + DOSFS_ToDosDateTime( time(NULL), &file->filedate, &file->filetime ); + return file; } @@ -375,35 +425,77 @@ int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize, } if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0); if (psize) *psize = S_ISDIR(st.st_mode) ? 0 : st.st_size; - DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime ); + DOSFS_ToDosDateTime( st.st_mtime, pdate, ptime ); return 1; } /*********************************************************************** - * FILE_Fstat + * FILE_GetDateTime * - * Stat a DOS handle. Return 1 if OK. + * Get the date and time of a file. */ -int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize, - WORD *pdate, WORD *ptime ) +int FILE_GetDateTime( HFILE hFile, WORD *pdate, WORD *ptime, BOOL refresh ) { - struct stat st; - int handle; + DOS_FILE *file; - if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return 0; - if (fstat( handle, &st ) == -1) + if (!(file = FILE_GetFile( hFile ))) return 0; + if (refresh) { - FILE_SetDosError(); - return 0; + struct stat st; + if (fstat( file->unix_handle, &st ) == -1) + { + FILE_SetDosError(); + return 0; + } + DOSFS_ToDosDateTime( st.st_mtime, &file->filedate, &file->filetime ); } - if (pattr) *pattr = FA_ARCHIVE | (S_ISDIR(st.st_mode) ? FA_DIRECTORY : 0); - if (psize) *psize = S_ISDIR(st.st_mode) ? 0 : st.st_size; - DOSFS_ToDosDateTime( &st.st_mtime, pdate, ptime ); + *pdate = file->filedate; + *ptime = file->filetime; return 1; } +/*********************************************************************** + * FILE_SetDateTime + * + * Set the date and time of a file. + */ +int FILE_SetDateTime( HFILE hFile, WORD date, WORD time ) +{ + DOS_FILE *file; + struct tm newtm; + struct utimbuf filetime; + + if (!(file = FILE_GetFile( hFile ))) return 0; + newtm.tm_sec = (time & 0x1f) * 2; + newtm.tm_min = (time >> 5) & 0x3f; + newtm.tm_hour = (time >> 11); + newtm.tm_mday = (date & 0x1f); + newtm.tm_mon = ((date >> 5) & 0x0f) - 1; + newtm.tm_year = (date >> 9) + 80; + + filetime.actime = filetime.modtime = mktime( &newtm ); + if (utime( file->unix_name, &filetime ) != -1) return 1; + FILE_SetDosError(); + return 0; +} + + +/*********************************************************************** + * FILE_Sync + */ +int FILE_Sync( HFILE hFile ) +{ + DOS_FILE *file; + + if (!(file = FILE_GetFile( hFile ))) return 0; + if (fsync( file->unix_handle ) != -1) return 1; + FILE_SetDosError(); + return 0; +} + + /*********************************************************************** * FILE_MakeDir */ @@ -461,20 +553,14 @@ int FILE_RemoveDir( LPCSTR path ) */ HFILE FILE_Dup( HFILE hFile ) { - int handle, newhandle; - HFILE dosHandle; + DOS_FILE *file; + HFILE handle; - if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR; - dprintf_file( stddeb, "FILE_Dup for handle %d\n",handle); - if ((newhandle = dup(handle)) == -1) - { - FILE_SetDosError(); - return HFILE_ERROR; - } - if ((dosHandle = FILE_AllocTaskHandle( newhandle )) == HFILE_ERROR) - close( newhandle ); - dprintf_file( stddeb, "FILE_Dup return handle %d\n",dosHandle); - return dosHandle; + dprintf_file( stddeb, "FILE_Dup for handle %d\n", hFile ); + if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( file )) != HFILE_ERROR) file->count++; + dprintf_file( stddeb, "FILE_Dup return handle %d\n", handle ); + return handle; } @@ -485,73 +571,138 @@ HFILE FILE_Dup( HFILE hFile ) */ HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 ) { + DOS_FILE *file; PDB *pdb = (PDB *)GlobalLock( GetCurrentPDB() ); - BYTE *files; - int handle, newhandle; + BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); + + dprintf_file( stddeb, "FILE_Dup2 for handle %d\n", hFile1 ); + if (!(file = FILE_GetFile( hFile1 ))) return HFILE_ERROR; - if ((handle = FILE_GetUnixTaskHandle( hFile1 )) == -1) return HFILE_ERROR; - dprintf_file( stddeb, "FILE_Dup2 for handle %d\n",handle); if ((hFile2 < 0) || (hFile2 >= (INT)pdb->nbFiles)) { DOS_ERROR( ER_InvalidHandle, EC_ProgramError, SA_Abort, EL_Disk ); return HFILE_ERROR; } - - if ((newhandle = dup(handle)) == -1) + if (files[hFile2] < MAX_OPEN_FILES) { - FILE_SetDosError(); - return HFILE_ERROR; + dprintf_file( stddeb, "FILE_Dup2 closing old handle2 %d\n", + files[hFile2] ); + FILE_Close( &DOSFiles[files[hFile2]] ); } - if (newhandle >= 0xff) - { - DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError, SA_Abort, EL_Disk ); - close( newhandle ); - return HFILE_ERROR; - } - files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr ); - if (files[hFile2] != 0xff) - { - dprintf_file( stddeb, "FILE_Dup2 closing old handle2 %d\n", - files[hFile2]); - close( files[hFile2] ); - } - files[hFile2] = (BYTE)newhandle; - dprintf_file( stddeb, "FILE_Dup2 return handle2 %d\n",newhandle); + files[hFile2] = (BYTE)(file - DOSFiles); + file->count++; + dprintf_file( stddeb, "FILE_Dup2 return handle2 %d\n", hFile2 ); return hFile2; } /*********************************************************************** - * FILE_OpenFile - * - * Implementation of API function OpenFile(). Returns a Unix file handle. + * FILE_Read */ -int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) +LONG FILE_Read( HFILE hFile, void *buffer, LONG count ) { + DOS_FILE *file; + LONG result; + + dprintf_file( stddeb, "FILE_Read: %d %p %ld\n", hFile, buffer, count ); + if (!(file = FILE_GetFile( hFile ))) return -1; + if (!count) return 0; + if ((result = read( file->unix_handle, buffer, count )) == -1) + FILE_SetDosError(); + return result; +} + + +/*********************************************************************** + * GetTempFileName (KERNEL.97) + */ +INT GetTempFileName( BYTE drive, LPCSTR prefix, UINT unique, LPSTR buffer ) +{ + int i; + UINT num = unique ? (unique & 0xffff) : time(NULL) & 0xffff; + char *p; + + if (drive & TF_FORCEDRIVE) + { + sprintf( buffer, "%c:", drive & ~TF_FORCEDRIVE ); + } + else + { + DIR_GetTempDosDir( buffer, 132 ); /* buffer must be at least 144 */ + strcat( buffer, "\\" ); + } + + p = buffer + strlen(buffer); + for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++; + sprintf( p, "%04x.tmp", num ); + + if (unique) + { + lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 ); + dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer ); + return unique; + } + + /* Now try to create it */ + + do + { + DOS_FILE *file; + if ((file = FILE_Create( buffer, 0666, TRUE )) != NULL) + { /* We created it */ + dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer ); + FILE_Close( file ); + break; + } + if (DOS_ExtendedError != ER_FileExists) break; /* No need to go on */ + num++; + sprintf( p, "%04x.tmp", num ); + } while (num != (unique & 0xffff)); + + lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 ); + dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer ); + return num; +} + + +/*********************************************************************** + * OpenFile (KERNEL.74) + */ +HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) +{ + DOS_FILE *file; + HFILE hFileRet; + WORD filedatetime[2]; const char *unixName, *dosName; char *p; - int handle, len, i, unixMode; - struct stat st; + int len, i, unixMode; ofs->cBytes = sizeof(OFSTRUCT); ofs->nErrCode = 0; if (mode & OF_REOPEN) name = ofs->szPathName; - dprintf_file( stddeb, "FILE_Openfile: %s %04x\n", name, mode ); + dprintf_file( stddeb, "OpenFile: %s %04x\n", name, mode ); + + /* First allocate a task handle */ + + if ((hFileRet = FILE_AllocTaskHandle( NULL )) == HFILE_ERROR) + { + ofs->nErrCode = DOS_ExtendedError; + dprintf_file( stddeb, "OpenFile: no more task handles.\n" ); + return HFILE_ERROR; + } /* OF_PARSE simply fills the structure */ if (mode & OF_PARSE) { - if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) - { - ofs->nErrCode = DOS_ExtendedError; - dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name); - return -1; - } + if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) goto error; lstrcpyn( ofs->szPathName, dosName, sizeof(ofs->szPathName) ); ofs->fFixedDisk = (GetDriveType( dosName[0]-'A' ) != DRIVE_REMOVABLE); - dprintf_file( stddeb, "FILE_Openfile: %s return = 0\n", name); - return 0; + dprintf_file( stddeb, "OpenFile(%s): OF_PARSE, res = '%s', %d\n", + name, ofs->szPathName, hFileRet ); + /* Return the handle, but close it first */ + FILE_FreeTaskHandle( hFileRet ); + return hFileRet; } /* OF_CREATE is completely different from all other options, so @@ -559,25 +710,10 @@ int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) if (mode & OF_CREATE) { - if ((unixName = DOSFS_GetUnixFileName( name, FALSE )) == NULL) - { - ofs->nErrCode = DOS_ExtendedError; - dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name); - return -1; - } - dprintf_file( stddeb, "FILE_OpenFile: creating '%s'\n", unixName ); - handle = open( unixName, O_TRUNC | O_RDWR | O_CREAT, 0666 ); - if (handle == -1) - { - FILE_SetDosError(); - ofs->nErrCode = DOS_ExtendedError; - dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name); - return -1; - } + if (!(file = FILE_Create( name, 0666, FALSE ))) goto error; lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ), sizeof(ofs->szPathName) ); - dprintf_file( stddeb, "FILE_Openfile: %s return = %d \n", name, handle); - return handle; + goto success; } /* Now look for the file */ @@ -638,30 +774,25 @@ int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) for (i = 0; ; i++) { - if (!DIR_GetDosPath( i, ofs->szPathName, len )) break; + if (!DIR_GetDosPath( i, ofs->szPathName, len )) goto not_found; strcat( ofs->szPathName, "\\" ); strcat( ofs->szPathName, name ); if ((unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE)) != NULL) - goto found; + break; } -not_found: - dprintf_file( stddeb, "FILE_OpenFile: '%s' not found\n", name ); - DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); - ofs->nErrCode = ER_FileNotFound; - dprintf_file( stddeb, "FILE_Openfile: %s return =-1\n", name); - return -1; - found: - dprintf_file( stddeb, "FILE_OpenFile: found '%s'\n", unixName ); + dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName ); lstrcpyn( ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE ), sizeof(ofs->szPathName) ); if (mode & OF_DELETE) { if (unlink( unixName ) == -1) goto not_found; - dprintf_file( stddeb, "FILE_Openfile: %s return = 0\n", name); - return 0; + dprintf_file( stddeb, "OpenFile(%s): OF_DELETE return = OK\n", name); + /* Return the handle, but close it first */ + FILE_FreeTaskHandle( hFileRet ); + return hFileRet; } switch(mode & 3) @@ -675,119 +806,45 @@ found: unixMode = O_RDONLY; break; } - if ((handle = FILE_OpenUnixFile( unixName, unixMode )) == -1) - goto not_found; - - if (fstat( handle, &st ) != -1) + if (!(file = FILE_OpenUnixFile( unixName, unixMode ))) goto not_found; + filedatetime[0] = file->filedate; + filedatetime[1] = file->filetime; + if ((mode & OF_VERIFY) && (mode & OF_REOPEN)) { - if ((mode & OF_VERIFY) && (mode & OF_REOPEN)) + if (memcmp( ofs->reserved, filedatetime, sizeof(ofs->reserved) )) { - if (memcmp( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) )) - { - dprintf_file( stddeb, "FILE_Openfile: %s return = -1\n", name); - close( handle ); - return -1; - } + FILE_Close( file ); + dprintf_file( stddeb, "OpenFile(%s): OF_VERIFY failed\n", name ); + /* FIXME: what error here? */ + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + goto error; } - memcpy( ofs->reserved, &st.st_mtime, sizeof(ofs->reserved) ); } + memcpy( ofs->reserved, filedatetime, sizeof(ofs->reserved) ); if (mode & OF_EXIST) { - close( handle ); - return 0; - } - dprintf_file( stddeb, "FILE_Openfile: %s return = %d\n", name,handle); - - return handle; -} - - -/*********************************************************************** - * FILE_Read - */ -LONG FILE_Read( HFILE hFile, LPSTR buffer, LONG count ) -{ - int handle; - LONG result; - - dprintf_file( stddeb, "FILE_Read: %d %p %ld\n", hFile, buffer, count ); - if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return -1; - if (!count) return 0; - if ((result = read( handle, buffer, count )) == -1) FILE_SetDosError(); - return result; -} - - -/*********************************************************************** - * GetTempFileName (KERNEL.97) - */ -INT GetTempFileName( BYTE drive, LPCSTR prefix, UINT unique, LPSTR buffer ) -{ - int i, handle; - UINT num = unique ? (unique & 0xffff) : time(NULL) & 0xffff; - char *p; - - if (drive & TF_FORCEDRIVE) - { - sprintf( buffer, "%c:", drive & ~TF_FORCEDRIVE ); - } - else - { - DIR_GetTempDosDir( buffer, 132 ); /* buffer must be at least 144 */ - strcat( buffer, "\\" ); + FILE_Close( file ); + /* Return the handle, but close it first */ + FILE_FreeTaskHandle( hFileRet ); + return hFileRet; } - p = buffer + strlen(buffer); - for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++; - sprintf( p, "%04x.tmp", num ); +success: /* We get here if the open was successful */ + dprintf_file( stddeb, "OpenFile(%s): OK, return = %d\n", name, hFileRet ); + FILE_SetTaskHandle( hFileRet, file ); + return hFileRet; - if (unique) - { - lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 ); - dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer ); - return unique; - } +not_found: /* We get here if the file does not exist */ + dprintf_file( stddeb, "OpenFile: '%s' not found\n", name ); + DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); + /* fall through */ - /* Now try to create it */ - - do - { - if ((handle = FILE_Create( buffer, 0666, TRUE )) != -1) - { /* We created it */ - dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer ); - close( handle ); - break; - } - if (DOS_ExtendedError != ER_FileExists) break; /* No need to go on */ - num++; - sprintf( p, "%04x.tmp", num ); - } while (num != (unique & 0xffff)); - - lstrcpyn( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 ); - dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer ); - return num; -} - - -/*********************************************************************** - * OpenFile (KERNEL.74) - */ -HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) -{ - int unixHandle; - HFILE handle; - - dprintf_file( stddeb, "OpenFile %s \n",name); - if ((unixHandle = FILE_OpenFile( name, ofs, mode )) == -1) - return HFILE_ERROR; - if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) - { - ofs->nErrCode = DOS_ExtendedError; - if (unixHandle) close( unixHandle ); - } - if (!unixHandle) FILE_FreeTaskHandle( handle ); - return handle; +error: /* We get here if there was an error opening the file */ + ofs->nErrCode = DOS_ExtendedError; + dprintf_file( stddeb, "OpenFile(%s): return = HFILE_ERROR\n", name ); + FILE_FreeTaskHandle( hFileRet ); + return HFILE_ERROR; } @@ -796,18 +853,12 @@ HFILE OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) */ HFILE _lclose( HFILE hFile ) { - int handle; + DOS_FILE *file; - - if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR; - dprintf_file( stddeb, "_lclose: doshandle %d unixhandle %d\n", hFile,handle ); - if (handle <= 2) - { - fprintf( stderr, "_lclose: internal error: closing handle %d\n", handle ); - exit(1); - } + dprintf_file( stddeb, "_lclose: handle %d\n", hFile ); + if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR; + FILE_Close( file ); FILE_FreeTaskHandle( hFile ); - close( handle ); return 0; } @@ -826,15 +877,15 @@ INT _lread( HFILE hFile, SEGPTR buffer, WORD count ) */ INT _lcreat( LPCSTR path, INT attr ) { - int unixHandle, mode; + DOS_FILE *file; HFILE handle; + int mode; dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr ); mode = (attr & 1) ? 0444 : 0666; - if ((unixHandle = FILE_Create( path, mode, FALSE )) == -1) - return HFILE_ERROR; - if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) - close( unixHandle ); + if (!(file = FILE_Create( path, mode, FALSE ))) return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR) + FILE_Close( file ); return handle; } @@ -844,15 +895,15 @@ INT _lcreat( LPCSTR path, INT attr ) */ INT _lcreat_uniq( LPCSTR path, INT attr ) { - int unixHandle, mode; + DOS_FILE *file; HFILE handle; + int mode; dprintf_file( stddeb, "_lcreat: %s %02x\n", path, attr ); mode = (attr & 1) ? 0444 : 0666; - if ((unixHandle = FILE_Create( path, mode, TRUE )) == -1) - return HFILE_ERROR; - if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) - close( unixHandle ); + if (!(file = FILE_Create( path, mode, TRUE ))) return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR) + FILE_Close( file ); return handle; } @@ -862,12 +913,13 @@ INT _lcreat_uniq( LPCSTR path, INT attr ) */ LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin ) { - int handle, origin, result; + DOS_FILE *file; + int origin, result; dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n", hFile, lOffset, nOrigin); - if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR; + if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR; switch(nOrigin) { case 1: origin = SEEK_CUR; break; @@ -875,8 +927,9 @@ LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin ) default: origin = SEEK_SET; break; } - if ((result = lseek( handle, lOffset, origin )) == -1) FILE_SetDosError(); - return (result == -1) ? HFILE_ERROR : result; + if ((result = lseek( file->unix_handle, lOffset, origin )) == -1) + FILE_SetDosError(); + return result; } @@ -885,7 +938,7 @@ LONG _llseek( HFILE hFile, LONG lOffset, INT nOrigin ) */ HFILE _lopen( LPCSTR path, INT mode ) { - int unixHandle; + DOS_FILE *file; int unixMode; HFILE handle; @@ -904,9 +957,9 @@ HFILE _lopen( LPCSTR path, INT mode ) unixMode = O_RDONLY; break; } - if ((unixHandle = FILE_Open( path, unixMode )) == -1) return HFILE_ERROR; - if ((handle = FILE_AllocTaskHandle( unixHandle )) == HFILE_ERROR) - close( unixHandle ); + if (!(file = FILE_Open( path, unixMode ))) return HFILE_ERROR; + if ((handle = FILE_AllocTaskHandle( file )) == HFILE_ERROR) + FILE_Close( file ); return handle; } @@ -944,20 +997,21 @@ LONG _hread( HFILE hFile, SEGPTR buffer, LONG count ) */ LONG _hwrite( HFILE hFile, LPCSTR buffer, LONG count ) { - int handle; + DOS_FILE *file; LONG result; dprintf_file( stddeb, "_hwrite: %d %p %ld\n", hFile, buffer, count ); - if ((handle = FILE_GetUnixTaskHandle( hFile )) == -1) return HFILE_ERROR; + if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR; if (count == 0) /* Expand or truncate at current position */ - result = ftruncate( handle, lseek( handle, 0, SEEK_CUR ) ); + result = ftruncate( file->unix_handle, + lseek( file->unix_handle, 0, SEEK_CUR ) ); else - result = write( handle, buffer, count ); + result = write( file->unix_handle, buffer, count ); if (result == -1) FILE_SetDosError(); - return (result == -1) ? HFILE_ERROR : result; + return result; } diff --git a/if1632/Makefile.in b/if1632/Makefile.in index 1db5b311c95..7e94b98747d 100644 --- a/if1632/Makefile.in +++ b/if1632/Makefile.in @@ -2,11 +2,33 @@ TOPSRC = @top_srcdir@ MODULE = if1632 -DLLS16 = commdlg.spec compobj.spec ddeml.spec gdi.spec kernel.spec \ - keyboard.spec mmsystem.spec mouse.spec ole2.spec ole2conv.spec \ - ole2disp.spec ole2nls.spec ole2prox.spec olecli.spec olesvr.spec \ - shell.spec sound.spec storage.spec stress.spec system.spec \ - toolhelp.spec user.spec win87em.spec winprocs.spec winsock.spec +DLLS16 = \ + commdlg.spec \ + compobj.spec \ + ddeml.spec \ + gdi.spec \ + kernel.spec \ + keyboard.spec \ + lzexpand.spec \ + mmsystem.spec \ + mouse.spec \ + ole2.spec \ + ole2conv.spec \ + ole2disp.spec \ + ole2nls.spec \ + ole2prox.spec \ + olecli.spec \ + olesvr.spec \ + shell.spec \ + sound.spec \ + storage.spec \ + stress.spec \ + system.spec \ + toolhelp.spec \ + user.spec \ + win87em.spec \ + winprocs.spec \ + winsock.spec DLLS32 = advapi32.spec comctl32.spec comdlg32.spec gdi32.spec kernel32.spec \ ole32.spec shell32.spec user32.spec winprocs32.spec winspool.spec diff --git a/if1632/callback.c b/if1632/callback.c index 346289e735a..7d22b17d457 100644 --- a/if1632/callback.c +++ b/if1632/callback.c @@ -38,7 +38,7 @@ LONG CallWindowProc( WNDPROC func, HWND hwnd, WORD message, if(!a->win32) fprintf(stderr,"Where is the Win32 callback?\n"); if (UsesLParamPtr(message)) - return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam ? PTR_SEG_TO_LIN(lParam): 0); + return RELAY32_CallWindowProcConvStruct(a->win32,hwnd,message,wParam,lParam); else return RELAY32_CallWindowProc(a->win32,hwnd,message,wParam,lParam); } diff --git a/if1632/lzexpand.spec b/if1632/lzexpand.spec new file mode 100644 index 00000000000..9f2e38d58b3 --- /dev/null +++ b/if1632/lzexpand.spec @@ -0,0 +1,15 @@ +name lzexpand +id 26 + +1 pascal LZCopy(word word) LZCopy +2 pascal16 LZOpenFile(ptr ptr word) LZOpenFile +3 pascal16 LZInit(word) LZInit +4 pascal LZSeek(word long word) LZSeek +5 pascal16 LZRead(word segptr word) LZRead +6 pascal16 LZClose(word) LZClose +7 pascal16 LZStart() LZStart +8 pascal CopyLZFile(word word) CopyLZFile +9 pascal16 LZDone() LZDone +10 pascal16 GetExpandedName(ptr ptr) GetExpandedName +#11 WEP +#12 ___EXPORTEDSTUB diff --git a/if1632/relay.c b/if1632/relay.c index b5f1a2b85b9..b0f3d9bbbab 100644 --- a/if1632/relay.c +++ b/if1632/relay.c @@ -52,7 +52,8 @@ struct dll_table_s dll_builtin_table[N_BUILTINS] = DLL_ENTRY_NOTUSED(COMPOBJ), DLL_ENTRY_NOTUSED(STORAGE), DLL_ENTRY(WINPROCS), - DLL_ENTRY_NOTUSED(DDEML) + DLL_ENTRY_NOTUSED(DDEML), + DLL_ENTRY(LZEXPAND) }; /* don't forget to increase N_BUILTINS in dlls.h if you add a dll */ diff --git a/if1632/relay32.c b/if1632/relay32.c index a10495894ea..4ec11047f61 100644 --- a/if1632/relay32.c +++ b/if1632/relay32.c @@ -17,7 +17,10 @@ #include "pe_image.h" #include "peexe.h" #include "relay32.h" +#include "struct32.h" +#include "stackframe.h" #include "xmalloc.h" +#include "ldt.h" #include "stddebug.h" #include "debug.h" @@ -124,7 +127,7 @@ LONG RELAY32_CallWindowProc( WNDPROC func, int hwnd, int message, int wParam, int lParam ) { int ret; -__asm__ ( + __asm__ ( "push %1;" "push %2;" "push %3;" @@ -136,6 +139,68 @@ __asm__ ( return ret; } +LONG RELAY32_CallWindowProcConvStruct( WNDPROC func, int hwnd, int message, + int wParam, LPARAM lParam16) +{ + WINDOWPOS32 wp; + union { + MINMAXINFO32 mmi; + NCCALCSIZE_PARAMS32 nccs; + CREATESTRUCT32 cs; + } st; + CREATESTRUCT *lpcs; + LONG result; + void *lParam; + if(!lParam16) + return RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)lParam16); + lParam = PTR_SEG_TO_LIN(lParam16); + switch(message) { + case WM_GETMINMAXINFO: + STRUCT32_MINMAXINFO16to32(lParam,&st.mmi); + result=RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)&st.mmi); + STRUCT32_MINMAXINFO32to16(&st.mmi,lParam); + return result; + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + STRUCT32_WINDOWPOS16to32(lParam,&wp); + result=RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)&wp); + STRUCT32_WINDOWPOS32to16(&wp,lParam); + return result; + case WM_NCCALCSIZE: + STRUCT32_NCCALCSIZE16to32Flat(lParam,&st.nccs); + if(((NCCALCSIZE_PARAMS*)lParam)->lppos) { + STRUCT32_WINDOWPOS16to32(((NCCALCSIZE_PARAMS*)lParam)->lppos,&wp); + st.nccs.lppos=℘ + } else + st.nccs.lppos= 0; + result=RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)&st.nccs); + STRUCT32_NCCALCSIZE32to16Flat(&st.nccs,lParam); + if(((NCCALCSIZE_PARAMS*)lParam)->lppos) + STRUCT32_WINDOWPOS32to16(&wp,((NCCALCSIZE_PARAMS*)lParam)->lppos); + return result; + case WM_NCCREATE: + lpcs = (CREATESTRUCT*)lParam; + STRUCT32_CREATESTRUCT16to32(lParam,&st.cs); + st.cs.lpszName = HIWORD(lpcs->lpszName) ? + PTR_SEG_TO_LIN(lpcs->lpszName) : (char*)lpcs->lpszName; + st.cs.lpszClass = HIWORD(lpcs->lpszClass) ? + PTR_SEG_TO_LIN(lpcs->lpszClass) : (char*)lpcs->lpszClass; + result=RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)&st.cs); + STRUCT32_CREATESTRUCT32to16(&st.cs,lParam); + lpcs->lpszName = HIWORD(st.cs.lpszName) ? + MAKE_SEGPTR(st.cs.lpszName) : (SEGPTR)st.cs.lpszName; + lpcs->lpszClass = HIWORD(st.cs.lpszClass) ? + MAKE_SEGPTR(st.cs.lpszClass) : (SEGPTR)st.cs.lpszClass; + return result; + case WM_GETTEXT: + case WM_SETTEXT: + return RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)lParam); + default: + fprintf(stderr,"No conversion function for message %d\n",message); + } + return RELAY32_CallWindowProc(func,hwnd,message,wParam,(int)lParam); +} + void RELAY32_MakeFakeModule(WIN32_builtin*dll) { NE_MODULE *pModule; diff --git a/include/debugger.h b/include/debugger.h index 42b42064d42..8cc7c48287a 100644 --- a/include/debugger.h +++ b/include/debugger.h @@ -89,6 +89,10 @@ extern void DEBUG_Print( const DBG_ADDR *addr, int count, char format ); extern void DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen ); extern void DEBUG_Help(void); extern void DEBUG_List( DBG_ADDR *addr, int count ); +extern void DEBUG_InitWalk(void); +extern void DEBUG_WndWalk( HWND ); +extern void DEBUG_WndDump( HWND ); +extern void DEBUG_QueueDump( HQUEUE ); /* debugger/memory.c */ extern BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size ); diff --git a/include/dlls.h b/include/dlls.h index 89c434ad9a7..00b5980958e 100644 --- a/include/dlls.h +++ b/include/dlls.h @@ -54,8 +54,9 @@ DECLARE_DLL(COMPOBJ) DECLARE_DLL(STORAGE) DECLARE_DLL(WINPROCS) DECLARE_DLL(DDEML) +DECLARE_DLL(LZEXPAND) -#define N_BUILTINS 25 +#define N_BUILTINS 26 extern struct dll_table_s dll_builtin_table[]; diff --git a/include/dos_fs.h b/include/dos_fs.h index 2bcca390f81..8a2631e7c60 100644 --- a/include/dos_fs.h +++ b/include/dos_fs.h @@ -25,7 +25,7 @@ typedef struct #define IS_END_OF_NAME(ch) (!(ch) || ((ch) == '/') || ((ch) == '\\')) -extern void DOSFS_ToDosDateTime( time_t *unixtime, WORD *pDate, WORD *pTime ); +extern void DOSFS_ToDosDateTime( time_t unixtime, WORD *pDate, WORD *pTime ); extern const char *DOSFS_ToDosFCBFormat( const char *name ); extern const char *DOSFS_ToDosDTAFormat( const char *name ); extern const char *DOSFS_IsDevice( const char *name ); diff --git a/include/file.h b/include/file.h index 9a4e0e45309..7893a96e44c 100644 --- a/include/file.h +++ b/include/file.h @@ -10,21 +10,21 @@ #include "windows.h" extern void FILE_SetDosError(void); -extern int FILE_GetUnixTaskHandle( HFILE handle ); extern void FILE_CloseAllFiles( HANDLE hPDB ); -extern int FILE_Open( LPCSTR path, int mode ); -extern int FILE_Create( LPCSTR path, int mode, int unique ); extern int FILE_Stat( LPCSTR unixName, BYTE *pattr, DWORD *psize, WORD *pdate, WORD *ptime ); +extern int FILE_GetDateTime( HFILE hFile, WORD *pdate, WORD *ptime, + BOOL refresh ); +extern int FILE_SetDateTime( HFILE hFile, WORD date, WORD time ); extern int FILE_Fstat( HFILE hFile, BYTE *pattr, DWORD *psize, WORD *pdate, WORD *ptime ); +extern int FILE_Sync( HFILE hFile ); extern int FILE_Unlink( LPCSTR path ); extern int FILE_MakeDir( LPCSTR path ); extern int FILE_RemoveDir( LPCSTR path ); extern HFILE FILE_Dup( HFILE hFile ); extern HFILE FILE_Dup2( HFILE hFile1, HFILE hFile2 ); -extern int FILE_OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ); -extern LONG FILE_Read( HFILE hFile, LPSTR buffer, LONG count ); +extern LONG FILE_Read( HFILE hFile, void *buffer, LONG count ); extern INT _lcreat_uniq( LPCSTR path, INT attr ); #endif /* __WINE_FILE_H */ diff --git a/include/lzexpand.h b/include/lzexpand.h new file mode 100644 index 00000000000..bf58839402c --- /dev/null +++ b/include/lzexpand.h @@ -0,0 +1,25 @@ +/* Includefile for the decompression library, lzexpand + * + * Copyright 1996 Marcus Meissner + */ + +LONG LZCopy(HFILE,HFILE); +HFILE LZOpenFile(LPCSTR,LPOFSTRUCT,UINT); +HFILE LZInit(HFILE); +LONG LZSeek(HFILE,LONG,INT); +INT LZRead(HFILE,SEGPTR,WORD); +void LZClose(HFILE); +INT LZStart(void); +LONG CopyLZFile(HFILE,HFILE); +void LZDone(void); +INT GetExpandedName(LPCSTR,LPSTR); + + +#define LZERROR_BADINHANDLE 0xFFFF /* -1 */ +#define LZERROR_BADOUTHANDLE 0xFFFE /* -2 */ +#define LZERROR_READ 0xFFFD /* -3 */ +#define LZERROR_WRITE 0xFFFC /* -4 */ +#define LZERROR_GLOBALLOC 0xFFFB /* -5 */ +#define LZERROR_GLOBLOCK 0xFFFA /* -6 */ +#define LZERROR_BADVALUE 0xFFF9 /* -7 */ +#define LZERROR_UNKNOWNALG 0xFFF8 /* -8 */ diff --git a/include/relay32.h b/include/relay32.h index 0fd7680bb64..c0cf4996bcf 100644 --- a/include/relay32.h +++ b/include/relay32.h @@ -7,6 +7,7 @@ #ifndef _RELAY32_H #define _RELAY32_H #include "pe_image.h" +#include "struct32.h" void RELAY32_Unimplemented(char *dll, int item); WIN32_builtin *RELAY32_GetBuiltinDLL(char *name); @@ -27,41 +28,10 @@ typedef struct tagWNDCLASSA{ char* lpszClassName; }WNDCLASSA; -struct WIN32_POINT{ - LONG x; - LONG y; -}; - -struct WIN32_MSG{ - DWORD hwnd; - DWORD message; - DWORD wParam; - DWORD lParam; - DWORD time; - struct WIN32_POINT pt; -}; - -struct WIN32_RECT{ - LONG left; - LONG top; - LONG right; - LONG bottom; -}; - -struct WIN32_PAINTSTRUCT{ - DWORD hdc; - DWORD fErase; - struct WIN32_RECT rcPaint; - DWORD fRestore; - DWORD fIncUpdate; - BYTE rgbReserved[32]; -}; - - ATOM USER32_RegisterClassA(WNDCLASSA *); LRESULT USER32_DefWindowProcA(DWORD hwnd,DWORD msg,DWORD wParam,DWORD lParam); -BOOL USER32_GetMessageA(struct WIN32_MSG* lpmsg,DWORD hwnd,DWORD min,DWORD max); -HDC USER32_BeginPaint(DWORD hwnd,struct WIN32_PAINTSTRUCT *lpps); -BOOL USER32_EndPaint(DWORD hwnd,struct WIN32_PAINTSTRUCT *lpps); +BOOL USER32_GetMessageA(MSG32* lpmsg,DWORD hwnd,DWORD min,DWORD max); +HDC USER32_BeginPaint(DWORD hwnd,PAINTSTRUCT32 *lpps); +BOOL USER32_EndPaint(DWORD hwnd,PAINTSTRUCT32 *lpps); #endif diff --git a/include/spy.h b/include/spy.h index 7fa75fb7495..d4d9c65421d 100644 --- a/include/spy.h +++ b/include/spy.h @@ -12,6 +12,9 @@ #define SPY_RESULT_OK 0x0000 #define SPY_RESULT_INVALIDHWND 0x0001 +#define SPY_MAX_MSGNUM WM_USER +#define SPY_MAX_INDENTLEVEL 64 + extern void EnterSpyMessage( int, HWND, WORD, WORD, LONG); extern void ExitSpyMessage( int, HWND, WORD, LONG); extern void SpyInit( void); diff --git a/include/struct32.h b/include/struct32.h index 37c1fd08e93..1e1de489986 100644 --- a/include/struct32.h +++ b/include/struct32.h @@ -1,6 +1,7 @@ /* Structure definitions for Win32 -- used only internally */ #ifndef _STRUCT32_H #define _STRUCT32_H +#include "handle32.h" typedef struct tagRECT32 { @@ -10,8 +11,8 @@ typedef struct tagRECT32 LONG bottom; } RECT32; -void USER32_RECT32to16(const RECT32*,RECT*); -void USER32_RECT16to32(const RECT*,RECT32*); +void STRUCT32_RECT32to16(const RECT32*,RECT*); +void STRUCT32_RECT16to32(const RECT*,RECT32*); typedef struct tagPOINT32 { @@ -25,9 +26,21 @@ typedef struct tagSIZE32 LONG cy; } SIZE32; -void PARAM32_POINT32to16(const POINT32*,POINT*); -void PARAM32_POINT16to32(const POINT*,POINT32*); -void PARAM32_SIZE16to32(const SIZE* p16, SIZE32* p32); +void STRUCT32_POINT32to16(const POINT32*,POINT*); +void STRUCT32_POINT16to32(const POINT*,POINT32*); +void STRUCT32_SIZE16to32(const SIZE* p16, SIZE32* p32); + +typedef struct tagMINMAXINFO32 +{ + POINT32 ptReserved; + POINT32 ptMaxSize; + POINT32 ptMaxPosition; + POINT32 ptMinTrackSize; + POINT32 ptMaxTrackSize; +} MINMAXINFO32; + +void STRUCT32_MINMAXINFO32to16(const MINMAXINFO32*,MINMAXINFO*); +void STRUCT32_MINMAXINFO16to32(const MINMAXINFO*,MINMAXINFO32*); typedef struct { DWORD style; @@ -51,4 +64,72 @@ typedef struct { #define CW_USEDEFAULT32 0x80000000 +typedef struct tagMSG32 +{ + DWORD hwnd; + DWORD message; + DWORD wParam; + DWORD lParam; + DWORD time; + POINT32 pt; +} MSG32; + +void STRUCT32_MSG16to32(MSG *msg16,MSG32 *msg32); +void STRUCT32_MSG32to16(MSG32 *msg32,MSG *msg16); + +typedef struct tagPAINTSTRUCT32 +{ + DWORD hdc; + DWORD fErase; + RECT32 rcPaint; + DWORD fRestore; + DWORD fIncUpdate; + BYTE rgbReserved[32]; +} PAINTSTRUCT32; + +typedef struct tagWINDOWPOS32 +{ + DWORD hwnd; + DWORD hwndInsertAfter; + LONG x; + LONG y; + LONG cx; + LONG cy; + DWORD flags; +} WINDOWPOS32; + +void STRUCT32_WINDOWPOS32to16(const WINDOWPOS32*,WINDOWPOS*); +void STRUCT32_WINDOWPOS16to32(const WINDOWPOS*,WINDOWPOS32*); + +typedef struct tagNCCALCSIZE_PARAMS32 +{ + RECT32 rgrc[3]; + WINDOWPOS32 *lppos; +} NCCALCSIZE_PARAMS32; + +void STRUCT32_NCCALCSIZE32to16Flat(const NCCALCSIZE_PARAMS32*, + NCCALCSIZE_PARAMS*); +void STRUCT32_NCCALCSIZE16to32Flat(const NCCALCSIZE_PARAMS* from, + NCCALCSIZE_PARAMS32* to); + +typedef struct tagCREATESTRUCT32 +{ + DWORD lpCreateParams; + DWORD hInstance; + DWORD hMenu; + DWORD hwndParent; + LONG cy; + LONG cx; + LONG y; + LONG x; + LONG style; + LPSTR lpszName; + LPSTR lpszClass; + DWORD dwExStyle; +} CREATESTRUCT32; +typedef CREATESTRUCT32 CREATESTRUCTA; + +void STRUCT32_CREATESTRUCT32to16(const CREATESTRUCT32*,CREATESTRUCT*); +void STRUCT32_CREATESTRUCT16to32(const CREATESTRUCT*,CREATESTRUCT32*); + #endif diff --git a/include/windows.h b/include/windows.h index 3d7c7b0d1d5..3fd0086e349 100644 --- a/include/windows.h +++ b/include/windows.h @@ -2553,6 +2553,32 @@ typedef struct { WORD wMilliseconds; } SYSTEMTIME, *LPSYSTEMTIME; +/* WinHelp internal structure */ +typedef struct { + WORD size; + WORD command; + LONG data; + LONG reserved; + WORD ofsFilename; + WORD ofsData; +} WINHELP,*LPWINHELP; + +typedef struct { + UINT mkSize; + BYTE mkKeyList; + BYTE szKeyPhrase[1]; +} MULTIKEYHELP, *LPMULTIKEYHELP; + +typedef struct { + WORD wStructSize; + WORD x; + WORD y; + WORD dx; + WORD dy; + WORD wMax; + char rgchMember[2]; +} HELPWININFO, *LPHELPWININFO; + #define HELP_CONTEXT 0x0001 #define HELP_QUIT 0x0002 #define HELP_INDEX 0x0003 diff --git a/include/wintypes.h b/include/wintypes.h index 3884f3b3f19..01df224faa6 100644 --- a/include/wintypes.h +++ b/include/wintypes.h @@ -143,6 +143,7 @@ typedef FARPROC HOOKPROC; #define _near #define PASCAL #define _pascal +#define __export #define VOID void #define WINAPI PASCAL #define CALLBACK PASCAL diff --git a/library/README.libres b/library/README.libres deleted file mode 100644 index 880272f3a01..00000000000 --- a/library/README.libres +++ /dev/null @@ -1,37 +0,0 @@ - WINElib resources: a proposal - -One of the current issues with WINElib is the inadequate support for accessing -resources by name. I propose the following technique (which I have already -begun to implement) to allow this: - - An internal table of resource entries is provided along with a registering - function for adding a resource to this table. 'winerc' should construct - *.c files much the same way as it does now with the inclusion of a single - static 'constructor' function that registers the associated resources with - the internal mechanism like so: - - static void DoIt() __attribute__ ((constructor)); - static void DoIt() - { - LIBRES_RegisterResource(hello3_MENU_MAIN__bytes, - sizeof(hello3_MENU_MAIN__bytes), - "MAIN", - RT_MENU); - LIBRES_RegisterResource(hello3_DIALOG_DIADEMO__bytes, - sizeof(hello3_DIALOG_DIADEMO__bytes), - "DIADEMO", - RT_DIALOG); - ... etc. ... - } - - The internal table can then be searched for the resource by name. - -The only potential drawback I've determined so far is this technique's -reliance on gcc's 'constructor' attribute, which disallows compilation with -some other compiler. However, I'm guessing that WINE is already heavily -dependent on gcc, so this is probably not too much of a factor. - -Any comments/suggestions/criticisms will be greatly appreciated. - -Thank you, ---Jim diff --git a/loader/module.c b/loader/module.c index f9dd6fe0f7d..a18f1da4e45 100644 --- a/loader/module.c +++ b/loader/module.c @@ -411,7 +411,7 @@ HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params ) /*********************************************************************** * MODULE_LoadExeHeader */ -HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs ) +HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) { struct mz_header_s mz_header; struct ne_header_s ne_header; @@ -427,15 +427,15 @@ HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs ) ((fastload && ((offset) >= fastload_offset) && \ ((offset)+(size) <= fastload_offset+fastload_length)) ? \ (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \ - (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \ - read( fd, (buffer), (size) ) == (size))) + (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \ + FILE_Read( hFile, (buffer), (size) ) == (size))) - lseek( fd, 0, SEEK_SET ); - if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) || + _llseek( hFile, 0, SEEK_SET ); + if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) || (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */ - lseek( fd, mz_header.ne_offset, SEEK_SET ); - if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header)) + _llseek( hFile, mz_header.ne_offset, SEEK_SET ); + if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header)) return (HMODULE)11; /* invalid exe */ if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */ @@ -477,8 +477,8 @@ HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs ) fastload_offset, fastload_length ); if ((fastload = (char *)malloc( fastload_length )) != NULL) { - lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET ); - if (read( fd, fastload, fastload_length ) != fastload_length) + _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET ); + if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length) { free( fastload ); fastload = NULL; @@ -572,8 +572,8 @@ HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs ) hModule, FALSE, FALSE, FALSE ); if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */ buffer = GlobalLock( pModule->nrname_handle ); - lseek( fd, ne_header.nrname_tab_offset, SEEK_SET ); - if (read( fd, buffer, ne_header.nrname_tab_length ) + _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET ); + if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length ) != ne_header.nrname_tab_length) return (HMODULE)11; /* invalid exe */ } else pModule->nrname_handle = 0; @@ -925,7 +925,8 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) LOADPARAMS *params = (LOADPARAMS *)paramBlock; #ifndef WINELIB WORD *pModRef, *pDLLs; - int i, fd; + HFILE hFile; + int i; hModule = MODULE_FindModule( name ); @@ -936,7 +937,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) /* Try to load the built-in first if not disabled */ if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule; - if ((fd = FILE_OpenFile( name, &ofs, OF_READ )) == -1) + if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR) { /* Now try the built-in even if disabled */ if ((hModule = MODULE_LoadBuiltin( name, TRUE ))) @@ -949,17 +950,20 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) /* Create the module structure */ - hModule = MODULE_LoadExeHeader( fd, &ofs ); + hModule = MODULE_LoadExeHeader( hFile, &ofs ); if (hModule < 32) { + /* FIXME: Hack because PE_LoadModule is recursive */ + int fd = dup( FILE_GetUnixHandle(hFile) ); + _lclose( hFile ); if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock ); - close(fd); + close( fd ); if (hModule < 32) fprintf( stderr, "LoadModule: can't load '%s', error=%d\n", name, hModule ); return hModule; } - close( fd ); + _lclose( hFile ); pModule = (NE_MODULE *)GlobalLock( hModule ); /* Allocate the segments for this module */ @@ -1017,6 +1021,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) if (pModule->flags & NE_FFLAGS_SELFLOAD) { + int fd; /* Handle self loading modules */ SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule); SELFLOADHEADER *selfloadheader; @@ -1069,6 +1074,8 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32); } + /* FIXME: we probably need a DOS handle here */ + fd = MODULE_OpenFile( hModule ); CallTo16_word_ww (selfloadheader->BootApp, pModule->self_loading_sel, hModule, fd); /* some BootApp procs overwrite the selector of dgroup */ diff --git a/loader/ne_image.c b/loader/ne_image.c index da9675d5a39..a2785c6b3a5 100644 --- a/loader/ne_image.c +++ b/loader/ne_image.c @@ -74,6 +74,7 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) oldselector = pSeg->selector; IF1632_Saved16_ss = pModule->self_loading_sel; IF1632_Saved16_sp = 0xFF00; + /* FIXME: we probably need to pass a DOS file handle here */ newselector = CallTo16_word_www(selfloadheader->LoadAppSeg, pModule->self_loading_sel, hModule, fd, segnum); if (newselector != oldselector) { diff --git a/misc/Makefile.in b/misc/Makefile.in index b9939f39912..4196c1cf030 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ escape.c \ keyboard.c \ lstr.c \ + lzexpand.c \ main.c \ network.c \ ole2.c \ diff --git a/misc/exec.c b/misc/exec.c index 6def5adcc31..fc0131b8d94 100644 --- a/misc/exec.c +++ b/misc/exec.c @@ -116,27 +116,75 @@ BOOL ExitWindows( DWORD dwReturnCode, WORD wReserved ) */ BOOL WinHelp(HWND hWnd, LPSTR lpHelpFile, WORD wCommand, DWORD dwData) { - char str[256]; - dprintf_exec(stddeb,"WinHelp(%s, %u, %lu)\n", - lpHelpFile, wCommand, dwData); - switch(wCommand) { - case 0: - case HELP_HELPONHELP: - GetWindowsDirectory(str, sizeof(str)); - strcat(str, "\\winhelp.exe winhelp.hlp"); - dprintf_exec(stddeb,"'%s'\n", str); - break; - case HELP_INDEX: - GetWindowsDirectory(str, sizeof(str)); - strcat(str, "\\winhelp.exe "); - strcat(str, lpHelpFile); - dprintf_exec(stddeb,"'%s'\n", str); - break; - case HELP_QUIT: - return TRUE; - default: + static WORD WM_WINHELP=0; + HWND hDest; + char szBuf[20]; + LPWINHELP lpwh; + HANDLE hwh; + void *data=0; + int size,dsize,nlen; + if (wCommand != HELP_QUIT) /* FIXME */ + if(WinExec("winhelp.exe -x",SW_SHOWNORMAL)<=32) return FALSE; + /* FIXME: Should be directed yield, to let winhelp open the window */ + Yield(); + if(!WM_WINHELP) { + strcpy(szBuf,"WM_WINHELP"); + WM_WINHELP=RegisterWindowMessage(MAKE_SEGPTR(szBuf)); + if(!WM_WINHELP) + return FALSE; } - WinExec(str, SW_SHOWNORMAL); - return(TRUE); + strcpy(szBuf,"MS_WINHELP"); + hDest = FindWindow(MAKE_SEGPTR(szBuf),0); + if(!hDest) + return FALSE; + switch(wCommand) + { + case HELP_CONTEXT: + case HELP_CONTENTS: + case HELP_SETCONTENTS: + case HELP_CONTEXTPOPUP: + case HELP_FORCEFILE: + case HELP_HELPONHELP: + case HELP_QUIT: + dsize=0; + break; + case HELP_KEY: + case HELP_PARTIALKEY: + case HELP_COMMAND: + data = PTR_SEG_TO_LIN(dwData); + dsize = strlen(data)+1; + break; + case HELP_MULTIKEY: + data = PTR_SEG_TO_LIN(dwData); + dsize = ((LPMULTIKEYHELP)data) -> mkSize; + break; + case HELP_SETWINPOS: + data = PTR_SEG_TO_LIN(dwData); + dsize = ((LPHELPWININFO)data) -> wStructSize; + break; + default: + fprintf(stderr,"Unknown help command %d\n",wCommand); + return FALSE; + } + if(lpHelpFile) + nlen = strlen(lpHelpFile)+1; + else + nlen = 0; + size = sizeof(WINHELP) + nlen + dsize; + hwh = GlobalAlloc(0,size); + lpwh = GlobalLock(hwh); + lpwh->size = size; + lpwh->command = wCommand; + if(nlen) { + lpwh->ofsFilename = sizeof(WINHELP); + strcpy(((char*)lpwh) + sizeof(WINHELP),lpHelpFile); + } + if(dsize) { + memcpy(((char*)lpwh)+sizeof(WINHELP)+nlen,data,dsize); + lpwh->ofsData = sizeof(WINHELP)+nlen; + } else + lpwh->ofsData = 0; + GlobalUnlock(hwh); + return SendMessage(hDest,WM_WINHELP,hWnd,hwh); } diff --git a/misc/lzexpand.c b/misc/lzexpand.c new file mode 100644 index 00000000000..57e5c8cd0d8 --- /dev/null +++ b/misc/lzexpand.c @@ -0,0 +1,492 @@ +/* + * LZ Decompression functions + * + * Copyright 1996 Marcus Meissner + */ +/* + * FIXME: return values might be wrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include "windows.h" +#include "file.h" +#include "lzexpand.h" +#include "stackframe.h" +#include "stddebug.h" +#include "debug.h" +#include "xmalloc.h" + +/* The readahead length of the decompressor. Reading single bytes + * using _lread() would be SLOW. + */ +#define GETLEN 2048 + +/* Format of first 14 byte of LZ compressed file */ +struct lzfileheader { + BYTE magic[8]; + BYTE compressiontype; + CHAR lastchar; + DWORD reallength; +}; +static BYTE LZMagic[8]={'S','Z','D','D',0x88,0xf0,0x27,0x33}; + +static struct lzstate { + HFILE lzfd; /* the handle used by the program */ + HFILE realfd; /* the real filedescriptor */ + CHAR lastchar; /* the last char of the filename */ + + DWORD reallength; /* the decompressed length of the file */ + DWORD realcurrent; /* the position the decompressor currently is */ + DWORD realwanted; /* the position the user wants to read from */ + + BYTE table[0x1000]; /* the rotating LZ table */ + UINT curtabent; /* CURrent TABle ENTry */ + + BYTE stringlen; /* length and position of current string */ + DWORD stringpos; /* from stringtable */ + + + WORD bytetype; /* bitmask within blocks */ + + BYTE *get; /* GETLEN bytes */ + DWORD getcur; /* current read */ + DWORD getlen; /* length last got */ +} *lzstates=NULL; +static int nroflzstates=0; + +/* reads one compressed byte, including buffering */ +#define GET(lzs,b) _lzget(lzs,&b) +#define GET_FLUSH(lzs) lzs->getcur=lzs->getlen; + +int +_lzget(struct lzstate *lzs,BYTE *b) { + if (lzs->getcurgetlen) { + *b = lzs->get[lzs->getcur++]; + return 1; + } else { + int ret = FILE_Read(lzs->realfd,lzs->get,GETLEN); + if (ret==HFILE_ERROR) + return HFILE_ERROR; + if (ret==0) + return 0; + lzs->getlen = ret; + lzs->getcur = 1; + *b = *(lzs->get); + return 1; + } +} +/* internal function, reads lzheader + * returns BADINHANDLE for non filedescriptors + * return 0 for file not compressed using LZ + * return UNKNOWNALG for unknown algorithm + * returns lzfileheader in *head + */ +static INT +read_header(HFILE fd,struct lzfileheader *head) { + BYTE buf[14]; + + if (_llseek(fd,0,SEEK_SET)==-1) + return LZERROR_BADINHANDLE; + + /* We can't directly read the lzfileheader struct due to + * structure element alignment + */ + if (FILE_Read(fd,buf,14)<14) + return 0; + memcpy(head->magic,buf,8); + memcpy(&(head->compressiontype),buf+8,1); + memcpy(&(head->lastchar),buf+9,1); + + /* FIXME: consider endianess on non-intel architectures */ + memcpy(&(head->reallength),buf+10,4); + + if (memcmp(head->magic,LZMagic,8)) + return 0; + if (head->compressiontype!='A') + return LZERROR_UNKNOWNALG; + return 1; +} +/* + * LZSTART [LZEXPAND.7] + */ +INT +LZStart(void) { + dprintf_file(stddeb,"LZStart(void)\n"); + return 1; +} + +/* + * LZINIT [LZEXPAND.3] + * + * initializes internal decompression buffers, returns lzfiledescriptor. + * (return value the same as hfSrc, if hfSrc is not compressed) + * on failure, returns error code <0 + * lzfiledescriptors range from 0x400 to 0x410 (only 16 open files per process) + * we use as much as we need, we just OR 0x400 to the passed HFILE. + * + * since _llseek uses the same types as libc.lseek, we just use the macros of + * libc + */ +HFILE +LZInit(HFILE hfSrc) { + struct lzfileheader head; + struct lzstate *lzs; + DWORD ret; + + dprintf_file(stddeb,"LZInit(%d)\n",hfSrc); + ret=read_header(hfSrc,&head); + if (ret<=0) { + _llseek(hfSrc,0,SEEK_SET); + return ret?ret:hfSrc; + } + lzstates=xrealloc(lzstates,(++nroflzstates)*sizeof(struct lzstate)); + lzs = lzstates+(nroflzstates-1); + + memset(lzs,'\0',sizeof(*lzs)); + lzs->realfd = hfSrc; + lzs->lzfd = hfSrc | 0x400; + lzs->lastchar = head.lastchar; + lzs->reallength = head.reallength; + + lzs->get = xmalloc(GETLEN); + lzs->getlen = 0; + lzs->getcur = 0; + + /* Yes, preinitialize with spaces */ + memset(lzs->table,' ',0x1000); + /* Yes, start 16 byte from the END of the table */ + lzs->curtabent = 0xff0; + return lzs->lzfd; +} + +/* + * LZDone [LZEXPAND.9] + */ + +void +LZDone(void) { + dprintf_file(stddeb,"LZDone()\n"); +} + +/* + * GetExpandedName [LZEXPAND.10] + * + * gets the full filename of the compressed file 'in' by opening it + * and reading the header + * + * "file." is being translated to "file" + * "file.bl_" (with lastchar 'a') is being translated to "file.bla" + * "FILE.BL_" (with lastchar 'a') is being translated to "FILE.BLA" + */ + +INT +GetExpandedName(LPCSTR in,LPSTR out) { + struct lzfileheader head; + HFILE fd; + OFSTRUCT ofs; + INT fnislowercased,ret,len; + LPSTR s,t; + + dprintf_file(stddeb,"GetExpandedName(%s)\n",in); + fd=OpenFile(in,&ofs,OF_READ); + if (fd==HFILE_ERROR) + return LZERROR_BADINHANDLE; + ret=read_header(fd,&head); + if (ret<=0) { + _lclose(fd); + return LZERROR_BADINHANDLE; + } + + /* This line will crash if the caller hasn't allocated enough memory + * for us. + */ + strcpy(out,in); + + /* look for directory prefix and skip it. */ + s=out; + while (NULL!=(t=strpbrk(s,"/\\:"))) + s=t+1; + + /* now mangle the basename */ + if (!*s) { + /* FIXME: hmm. shouldn't happen? */ + fprintf(stddeb,__FILE__":GetExpandedFileName(), specified a directory or what? (%s)\n",in); + _lclose(fd); + return 1; + } + /* see if we should use lowercase or uppercase on the last char */ + fnislowercased=1; + t=s+strlen(s)-1; + while (t>=out) { + if (!isalpha(*t)) { + t--; + continue; + } + fnislowercased=islower(*t); + break; + } + if (isalpha(head.lastchar)) { + if (fnislowercased) + head.lastchar=tolower(head.lastchar); + else + head.lastchar=toupper(head.lastchar); + } + + /* now look where to replace the last character */ + if (NULL!=(t=strchr(s,'.'))) { + if (t[1]=='\0') { + t[0]='\0'; + } else { + len=strlen(t)-1; + if (t[len]=='_') + t[len]=head.lastchar; + } + } /* else no modification necessary */ + _lclose(fd); + return 1; +} + +/* + * LZRead [LZEXPAND.5] + * just as normal read, but reads from LZ special fd and uncompresses. + */ +INT +LZRead(HFILE fd,SEGPTR segbuf,WORD toread) { + int i,howmuch; + BYTE b; + BYTE *buf; + struct lzstate *lzs; + + dprintf_file(stddeb,"LZRead(%d,%08lx,%d)\n",fd,segbuf,toread); + howmuch=toread; + for (i=0;istringlen) { \ + b = lzs->table[lzs->stringpos]; \ + lzs->stringpos = (lzs->stringpos+1)&0xFFF; \ + lzs->stringlen--; \ + } else { \ + if (!(lzs->bytetype&0x100)) { \ + if (1!=GET(lzs,b)) \ + return toread-howmuch; \ + lzs->bytetype = b|0xFF00; \ + } \ + if (lzs->bytetype & 1) { \ + if (1!=GET(lzs,b)) \ + return toread-howmuch; \ + } else { \ + BYTE b1,b2; \ + \ + if (1!=GET(lzs,b1)) \ + return toread-howmuch; \ + if (1!=GET(lzs,b2)) \ + return toread-howmuch; \ + /* Format: \ + * b1 b2 \ + * AB CD \ + * where CAB is the stringoffset in the table\ + * and D+3 is the len of the string \ + */ \ + lzs->stringpos = b1|((b2&0xf0)<<4); \ + lzs->stringlen = (b2&0xf)+2; \ + /* 3, but we use a byte already below ... */\ + b = lzs->table[lzs->stringpos];\ + lzs->stringpos = (lzs->stringpos+1)&0xFFF;\ + } \ + lzs->bytetype>>=1; \ + } \ + /* store b in table */ \ + lzs->table[lzs->curtabent++]= b; \ + lzs->curtabent &= 0xFFF; \ + lzs->realcurrent++; + + /* if someone has seeked, we have to bring the decompressor + * to that position + */ + if (lzs->realcurrent!=lzs->realwanted) { + /* if the wanted position is before the current position + * I see no easy way to unroll ... We have to restart at + * the beginning. *sigh* + */ + if (lzs->realcurrent>lzs->realwanted) { + /* flush decompressor state */ + _llseek(lzs->realfd,14,SEEK_SET); + GET_FLUSH(lzs); + lzs->realcurrent= 0; + lzs->bytetype = 0; + lzs->stringlen = 0; + memset(lzs->table,' ',0x1000); + lzs->curtabent = 0xFF0; + } + while (lzs->realcurrentrealwanted) { + DECOMPRESS_ONE_BYTE; + } + } + + buf=PTR_SEG_TO_LIN(segbuf); + while (howmuch) { + DECOMPRESS_ONE_BYTE; + lzs->realwanted++; + *buf++ = b; + howmuch--; + } + return toread; +#undef DECOMPRESS_ONE_BYTE +} + +/* + * LZSeek [LZEXPAND.4] + * + * works as the usual _llseek + */ + +LONG +LZSeek(HFILE fd,LONG off,INT type) { + int i; + struct lzstate *lzs; + LONG lastwanted,newwanted; + + dprintf_file(stddeb,"LZSeek(%d,%ld,%d)\n",fd,off,type); + for (i=0;irealwanted; + newwanted = lzs->realwanted; + switch (type) { + case 1: /* SEEK_CUR */ + newwanted += off; + break; + case 2: /* SEEK_END */ + newwanted = lzs->reallength-off; + break; + default:/* SEEK_SET */ + newwanted = off; + break; + } + if (newwanted>lzs->reallength) + return LZERROR_BADVALUE; + if (newwanted<0) + return LZERROR_BADVALUE; + lzs->realwanted = newwanted; + return lastwanted; +} + +/* + * LZCopy [LZEXPAND.1] + * + * Copies everything from src to dest + * if src is a LZ compressed file, it will be uncompressed. + * will return the number of bytes written to dest or errors. + */ +LONG +LZCopy(HFILE src,HFILE dest) { + int i,ret,wret; + LONG len; +#define BUFLEN 1000 + BYTE buf[BUFLEN]; + INT (*xread)(HFILE,SEGPTR,WORD); + + dprintf_file(stddeb,"LZCopy(%d,%d)\n",src,dest); + for (i=0;itop; - ysrc = yinc * ydst; + ysrc = yinc * ydst + (vswap ? heightSrc<<16 : 0); } else { yinc = ((int)heightDst << 16) / heightSrc; ysrc = visRectSrc->top; - ydst = yinc * ysrc; + ydst = yinc * ysrc - (vswap ? (heightDst-1)<<16 : 0); } while(vstretch ? (ydst < visRectDst->bottom) : (ysrc < visRectSrc->bottom)) @@ -685,7 +685,8 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, /* Stretch or shrink it */ if (hstretch) - BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left, + BITBLT_StretchRow( rowSrc, rowDst, visRectDst->left + + (hswap ? widthDst : 0), visRectDst->right-visRectDst->left, xinc, mode); else BITBLT_ShrinkRow( rowSrc, rowDst, visRectSrc->left, visRectSrc->right-visRectSrc->left, xinc, mode); @@ -714,7 +715,7 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, /* Store the destination row */ - pixel = rowDst + visRectDst->right - 1; + pixel = rowDst + visRectDst->right - 1 + (hswap ? widthDst : 0); if (vswap) y = visRectDst->bottom - (vstretch ? ydst : ydst >> 16); else @@ -972,7 +973,8 @@ static BOOL BITBLT_GetVisRectangles( DC *dcDst, short xDst, short yDst, if (!dcSrc) return TRUE; SetRect( &tmpRect, xSrc, ySrc, xSrc + widthSrc, ySrc + heightSrc ); - GetRgnBox( dcSrc->w.hGCClipRgn, &clipRect ); + /* Apparently the clip region is only for output, so use hVisRgn here */ + GetRgnBox( dcSrc->w.hVisRgn, &clipRect ); OffsetRect( &clipRect, dcSrc->w.DCOrgX, dcSrc->w.DCOrgY ); if (!IntersectRect( visRectSrc, &tmpRect, &clipRect )) return FALSE; diff --git a/objects/region.c b/objects/region.c index 1874a911be8..7e7e2907592 100644 --- a/objects/region.c +++ b/objects/region.c @@ -361,9 +361,11 @@ BOOL EqualRgn( HRGN rgn1, HRGN rgn2 ) */ static int REGION_CopyRegion( RGNOBJ *src, RGNOBJ *dest ) { + Region tmprgn; if (src->xrgn) { - Region tmprgn = XCreateRegion(); + if (src->xrgn == dest->xrgn) return COMPLEXREGION; + tmprgn = XCreateRegion(); if (!dest->xrgn) dest->xrgn = XCreateRegion(); XUnionRegion( tmprgn, src->xrgn, dest->xrgn ); XDestroyRegion( tmprgn ); @@ -401,11 +403,14 @@ BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, int x, int y ) /*********************************************************************** * CombineRgn (GDI.451) + * + * The behavior is correct even if src and dest regions are the same. */ INT CombineRgn( HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode ) { RGNOBJ *destObj, *src1Obj, *src2Obj; - + Region destrgn; + dprintf_region(stddeb, "CombineRgn: "NPFMT","NPFMT" -> "NPFMT" mode=%x\n", hSrc1, hSrc2, hDest, mode ); @@ -445,29 +450,32 @@ INT CombineRgn( HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode ) /* Perform the operation with the two X regions */ - if (!destObj->xrgn) destObj->xrgn = XCreateRegion(); + if (!(destrgn = XCreateRegion())) return ERROR; switch(mode) { case RGN_AND: - XIntersectRegion( src1Obj->xrgn, src2Obj->xrgn, destObj->xrgn ); + XIntersectRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn ); break; case RGN_OR: - XUnionRegion( src1Obj->xrgn, src2Obj->xrgn, destObj->xrgn ); + XUnionRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn ); break; case RGN_XOR: - XXorRegion( src1Obj->xrgn, src2Obj->xrgn, destObj->xrgn ); + XXorRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn ); break; case RGN_DIFF: - XSubtractRegion( src1Obj->xrgn, src2Obj->xrgn, destObj->xrgn ); + XSubtractRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn ); break; default: + XDestroyRegion( destrgn ); return ERROR; } + if (destObj->xrgn) XDestroyRegion( destObj->xrgn ); + destObj->xrgn = destrgn; if (XEmptyRegion(destObj->xrgn)) { XDestroyRegion( destObj->xrgn ); destObj->xrgn = 0; return NULLREGION; } - else return COMPLEXREGION; + return COMPLEXREGION; } diff --git a/programs/progman/main.c b/programs/progman/main.c index f6173e251a5..677512191c0 100644 --- a/programs/progman/main.c +++ b/programs/progman/main.c @@ -9,6 +9,7 @@ #include "license.h" #include "progman.h" #ifdef WINELIB +#include #include #include #endif diff --git a/rc/parser.h b/rc/parser.h index dc667bab134..38e5028e157 100644 --- a/rc/parser.h +++ b/rc/parser.h @@ -91,6 +91,8 @@ gen_res *make_menu(gen_res*); gen_res *add_resource(gen_res*,gen_res*); +void add_str_tbl_elm(int,char*); + void create_output(gen_res*); void set_out_file(char*); diff --git a/rc/parser.l b/rc/parser.l index 945ff8299e1..ed39e54a9f1 100644 --- a/rc/parser.l +++ b/rc/parser.l @@ -10,6 +10,8 @@ #include #include "parser.h" #include "y.tab.h" + +int line_number=1; %} %% ACCELERATORS return ACCELERATORS; @@ -70,7 +72,8 @@ VIRTKEY return VIRTKEY; [A-Za-z][A-Za-z_0-9]* yylval.str=strdup(yytext);return IDENT; \"[^"]*\" yylval.str=parse_c_string(yytext);return STRING; \'[^']*\' yylval.str=strdup(yytext+1);return SINGLE_QUOTED; -[ \t\n\r] ; +\n { line_number++; } +[ \t\r] ; . return yytext[0]; %% diff --git a/rc/parser.y b/rc/parser.y index 121c508c929..3cbd0398c55 100644 --- a/rc/parser.y +++ b/rc/parser.y @@ -5,6 +5,7 @@ */ #include +#include #include "parser.h" #include "windows.h" %} @@ -29,7 +30,7 @@ %type iconinfo menu menu_body item_definitions rcdata raw_data raw_elements %type stringtable strings versioninfo %type acc_options item_options -%type