From 329f0680e4d3c04b2148a3955ed3a72b37ccbd33 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 14 Apr 1996 13:21:20 +0000 Subject: [PATCH] Release 960414 Sun Apr 14 12:51:27 1996 Alexandre Julliard * [controls/menu.c] [include/dialog.h] [windows/dialog.c] Made the resource loading code always use the correct Windows layout for Winelib on other CPUs. * [include/module.h] [loader/module.c] Added self handle in NE_MODULE structure, so we can use a pointer instead of a handle. Added function MODULE_GetPtr() to validate a HMODULE. * [memory/heap.c] Implemented Win32 heap management. * [memory/selector.c] Fix selector limit for huge blocks. Sat Apr 13 00:19:12 1996 Huw D. M. Davies * [objects/metafile.c] Fixed memcpy bug to allow memory based metafiles to work. Fri Apr 12 19:25:41 1996 Frans van Dorsselaer * [controls/edit.c] [controls/EDIT.TODO] Complete rewrite. Everything changed: new features, new bugs. Main addition: WordWrap. Fri Apr 12 20:29:55 1996 Tristan Tarrant * [resources/sysres_It.rc] Fixed a few mistakes in the file and resized some of the controls. Fri Apr 12 09:55:13 1996 John Harvey * [misc/winsocket.c] Fixed broken #if defined that stopped unixware compiling. * [win32/resource.c] Added missing return to end of FindResource32. Thu Apr 11 18:00:00 1996 Alex Korobka * [windows/keyboard.c] [windows/event.c] Fixed GetKeyState for mouse buttons. * [windows/message.c] WM_MOUSEACTIVATE wasn't sent in some cases. Wed Apr 10 18:59:53 1996 Niels de Carpentier * [objects/font.c] Match slightly bigger font if height negative. Mon Apr 8 13:46:15 1996 Deano Calver * [multimedia/mmsystem.c] Changed read's to FILE_read's in mmsystem to fix mmio bug. Sun Apr 7 21:40:29 1996 Albrecht Kleine * [misc/commdlg.c] [resources/sysres_En.rc] [resources/sysres_De.rc] Introduced ColorDlgProc() for ChooseColor() and replaced fitting En-,De- resources. As written in TODO: some national language support is needed here. --- ANNOUNCE | 18 +- ChangeLog | 67 + controls/EDIT.TODO | 118 +- controls/combo.c | 3 +- controls/edit.c | 5742 +++++++++++++++++-------------------- controls/listbox.c | 2 +- controls/menu.c | 6 +- debugger/dbg.y | 18 + debugger/hash.c | 2 +- if1632/kernel32.spec | 22 +- include/debug.h | 201 +- include/debugger.h | 1 + include/dialog.h | 21 +- include/handle32.h | 2 +- include/module.h | 80 +- include/pe_image.h | 2 + include/stddebug.h | 2 + include/winbase.h | 49 +- include/winnt.h | 23 + include/wintypes.h | 27 +- library/miscstubs.c | 5 + loader/module.c | 143 +- loader/ne_image.c | 23 +- loader/ne_resource.c | 20 +- loader/pe_image.c | 58 +- loader/resource.c | 16 +- loader/signal.c | 3 - loader/task.c | 8 +- memory/Makefile.in | 1 + memory/global.c | 2 + memory/heap.c | 1091 +++++++ memory/local.c | 2 +- memory/selector.c | 6 +- misc/commdlg.c | 1093 ++++++- misc/winsocket.c | 2 +- multimedia/mmsystem.c | 8 +- objects/font.c | 4 +- objects/metafile.c | 2 +- programs/progman/main.c | 4 +- programs/progman/string.c | 4 +- rc/parser.h | 4 - resources/TODO | 24 + resources/sysres_De.rc | 41 +- resources/sysres_En.rc | 41 +- resources/sysres_It.rc | 50 +- tools/build.c | 15 +- win32/Makefile.in | 1 - win32/heap.c | 191 -- win32/init.c | 2 +- win32/resource.c | 18 +- win32/thread.c | 10 +- win32/time.c | 2 +- windows/dialog.c | 96 +- windows/event.c | 8 +- windows/keyboard.c | 18 +- windows/message.c | 34 +- 56 files changed, 5699 insertions(+), 3757 deletions(-) create mode 100644 include/winnt.h create mode 100644 memory/heap.c delete mode 100644 win32/heap.c diff --git a/ANNOUNCE b/ANNOUNCE index e2d0c9868c0..7f3bb2f058e 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,14 +1,14 @@ -This is release 960405 of Wine the MS Windows emulator. This is still a +This is release 960414 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-960405: (see ChangeLog for details) - - Faster text display. - - Support for SCO OpenServer 5. - - Cleaner Win32 module handling. +WHAT'S NEW with Wine-960414: (see ChangeLog for details) + - Complete rewrite of the edit control. + - Better color selection dialog. + - Win32 heap management. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -17,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-960405.tar.gz - tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960405.tar.gz - ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960405.tar.gz - aris.com:/pub/linux/ALPHA/Wine/development/Wine-960405.tar.gz + sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960414.tar.gz + tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960414.tar.gz + ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960414.tar.gz + aris.com:/pub/linux/ALPHA/Wine/development/Wine-960414.tar.gz It should also be available from any site that mirrors tsx-11 or sunsite. diff --git a/ChangeLog b/ChangeLog index f37c6bd62b5..46b0a5bdd76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,70 @@ +---------------------------------------------------------------------- +Sun Apr 14 12:51:27 1996 Alexandre Julliard + + * [controls/menu.c] [include/dialog.h] [windows/dialog.c] + Made the resource loading code always use the correct Windows + layout for Winelib on other CPUs. + + * [include/module.h] [loader/module.c] + Added self handle in NE_MODULE structure, so we can use a pointer + instead of a handle. + Added function MODULE_GetPtr() to validate a HMODULE. + + * [memory/heap.c] + Implemented Win32 heap management. + + * [memory/selector.c] + Fix selector limit for huge blocks. + +Sat Apr 13 00:19:12 1996 Huw D. M. Davies + + * [objects/metafile.c] + Fixed memcpy bug to allow memory based metafiles to work. + +Fri Apr 12 19:25:41 1996 Frans van Dorsselaer + + * [controls/edit.c] [controls/EDIT.TODO] + Complete rewrite. Everything changed: new features, new bugs. + Main addition: WordWrap. + +Fri Apr 12 20:29:55 1996 Tristan Tarrant + + * [resources/sysres_It.rc] + Fixed a few mistakes in the file and resized some of the controls. + +Fri Apr 12 09:55:13 1996 John Harvey + + * [misc/winsocket.c] + Fixed broken #if defined that stopped unixware compiling. + + * [win32/resource.c] + Added missing return to end of FindResource32. + +Thu Apr 11 18:00:00 1996 Alex Korobka + + * [windows/keyboard.c] [windows/event.c] + Fixed GetKeyState for mouse buttons. + + * [windows/message.c] + WM_MOUSEACTIVATE wasn't sent in some cases. + +Wed Apr 10 18:59:53 1996 Niels de Carpentier + + * [objects/font.c] + Match slightly bigger font if height negative. + +Mon Apr 8 13:46:15 1996 Deano Calver + + * [multimedia/mmsystem.c] + Changed read's to FILE_read's in mmsystem to fix mmio bug. + +Sun Apr 7 21:40:29 1996 Albrecht Kleine + + * [misc/commdlg.c] [resources/sysres_En.rc] [resources/sysres_De.rc] + Introduced ColorDlgProc() for ChooseColor() and replaced fitting + En-,De- resources. + As written in TODO: some national language support is needed here. + ---------------------------------------------------------------------- Fri Apr 5 15:22:55 1996 Alexandre Julliard diff --git a/controls/EDIT.TODO b/controls/EDIT.TODO index f2d404f7764..a1908748d2c 100644 --- a/controls/EDIT.TODO +++ b/controls/EDIT.TODO @@ -1,33 +1,111 @@ -- Find all the remaining bugs! +This file gives some information about the code in edit.c. If you want to +change, add, or fix code, please read this text. If you're not interested +in doing actual work on edit.c only C & D will be of interest to you. -- ES_LEFT, ES_RIGHT and ES_CENTER. ES_RIGHT and ES_CENTER cannot be - used with single line edit controls or be combined with ES_AUTOHSCROLL. +A) basic policy +B) special functions +C) not implemented +D) known bugs -- Hide selection when window loses focus and ES_NOHIDESEL to disable - this functionality. +A) Basic Policy -- ES_LOWERCASE and ES_UPPERCASE. +The code has been made in such a way, that functions try to call other +(documented) functions if that is sufficient. This might sometimes not be +the most efficient way, but it keeps the code clear. This way I tried to keep +the number of functions that rely on the internal EDITSTATE structure as +low as possible. For instance EDIT_WM_Cut() simply calls EDIT_WM_Copy() and +EDIT_WM_Clear(). The latter two are well documented message handlers, so +as long as they are right EDIT_WM_Cut() will never have to change again. -- ES_OEMCONVERT. Probably won't do anything very much. +Example: +The best thing to do, when you want to know the offset of line 3, is calling +EDIT_EM_LineIndex(). Again this is a well documented message handler. Don't +look at es->LineDefs[2].offset. It would just be another reference to the +internal structure, and that would make it more difficult to change things. +Refer to EDIT_WM_???? and EDIT_EM_????? functions as much as possible. -- ES_WANTRETURN and Ctrl-Enter to move to next line when this - functionality is enabled. +The WND * pointer is used internally whenever possible. Although it is not +the real HWND, it improves performance enough to use it. -- Implement undo buffer correctly. Windows allows the user to undo - entered text as well as deleted text. You can also undo an undo. +All displaying is done by invalidating regions / rects. Only +EDIT_EM_LineScroll() uses direct painting. This way things become much +faster. Although sometimes the response time might appear to be slow, it +would be much slower even, when everything would be painted instantly. This +is especially true for scrollbar tracking and selection changes.. -- Add word wrap - this is a very big change! -I'm doing a rewrite on edit.c. Please e-mail me if you want -to work on edit.c as well, so we can synchronize. -Bugs in the current version, known to me: -- An empty document still contains "\r\n" -- UNDO is unstable (incomplete, and it can cause a segfault) -- WM_LBUTTONDBLCLK lets you select whole words, but doesn't set - the caret at the end of the selection -- Scrolling (left-right) works, but the scrollbar doesn't +B) Special functions +The edit control needs to use local heap memory because applications may +rely on EM_GETHANDLE. This is bad, but it can't be helped, we have to live +with that. For this reason there is a nice EDIT_GetPointer() function, +which locks the heap buffer *only once*, no matter how often it is called. +Only at the end of the message handler EDIT_ReleasePointer() is called. You +don't have to worry about unlocking the heap. Calling EDIT_GetPointer() is +very fast if the buffer is already locked. +This way, the buffer gets locked / unlock only once every message, although +EDIT_GetPointer() may actually have been called a hundred times. +Only when the actual HLOCAL is needed (for example to ReAlloc), a call to +EDIT_ReleasePointer() is needed. Look for instance in EDIT_MakeFit(). + +This brings us to EDIT_MakeFit(). It automatically re-allocates the buffer +if the size parameter > buffersize. If everything is successful TRUE is +returned, otherwise FALSE. Only when the buffer contents may grow you need +to call EDIT_MakeFit(). Currently this is only in EDIT_ReplaceSel() and +EDIT_WM_SetText(). + +EDIT_BuildLineDefs() is the most important function in edit.c. It builds +the internal EDITSTATE structure. As soon as text *might* have changed, or +when the appearance of the text on the screen *might* have changed, call +this function ! This includes changes of screen size, change of the font, +clipboard actions, etc. etc. Most other functions that rely on EDITSTATE, +rely on the stuff this function builds. + + + +C) Not Implemented + +- ES_PASSWORD +- ES_CENTER +- ES_RIGHT +- EM_SETRECT +- EM_SETRECTNP +- EM_FMTLINES +- ES_AUTOVSCROLL (every multi line *is* auto vscroll) +- ES_AUTOHSCROLL (multi line can be yes or no, but single line only yes) +- WM_UNDO (=EM_UNDO) +- EM_CANUNDO +- EM_SCROLL (scrolling works, but this appears to be an undocumented message) +- ES_LOWERCASE +- ES_UPPERCASE +- ES_OEMCONVERT +- ES_WANTRETURN +- probably much, MUCH more + +I encountered several undocumented messages, or message parameters. +EditWndProc() reports any unknown message with an id > WM_USER. + + + +D) Known bugs. + +- Scrolling is weird, sometimes. The current code makes the scrollbar + of Notepad work, but the scrollbar code itself is broken. Currently + the scroll code of edit.c is *not* according to specs. Instead, it + is according to the broken scrollbar code. If that gets fixed, this + should be fixed, too. +- The clipboard is broken. Whenever things go wrong with + cut/copy/paste, it is probably the clipboard that messes up things, + not edit.c. +- With Notepad, if you select New File a couple of times and enter + text, the buffer is sometimes corrupted. +- Switching on/off WordWrap with Notepad sometimes corrupts the buffer. + + +I am still very actively changing things. Especially I am working +on Undo capabilities. If you want to do things, other than bug fixes, +please mail me so we can synchronize. Frans van Dorsselaer dorssel@rulhm1.LeidenUniv.nl diff --git a/controls/combo.c b/controls/combo.c index 8ac780f58d6..5a616ce2374 100644 --- a/controls/combo.c +++ b/controls/combo.c @@ -1013,7 +1013,8 @@ INT DlgDirListComboBox( HWND hDlg, SEGPTR path, INT idCBox, if (idCBox) { SendDlgItemMessage( hDlg, idCBox, CB_RESETCONTENT, 0, 0 ); - ret = (SendDlgItemMessage( hDlg, idCBox, CB_DIR, wType, path ) >= 0); + ret = (SendDlgItemMessage( hDlg, idCBox, CB_DIR, + wType, (LPARAM)path ) >= 0); } if (idStatic) { diff --git a/controls/edit.c b/controls/edit.c index 37d95adc105..d49bd0413a3 100644 --- a/controls/edit.c +++ b/controls/edit.c @@ -1,3146 +1,2806 @@ /* - * Edit control + * Edit control * - * Copyright David W. Metcalfe, 1994 - * Copyright William Magro, 1995, 1996 - * Copyright Frans van Dorsselaer, 1996 + * Copyright David W. Metcalfe, 1994 + * Copyright William Magro, 1995, 1996 + * Copyright Frans van Dorsselaer, 1996 * - * Note: I'm doing a rewrite in order to implement word wrap - * Please e-mail me if you want to word on edit.c as well, so - * we can synchronize. - * - * Frans van Dorsselaer - * dorssel@rulhm1.LeidenUniv.nl + */ + +/* + * UNDER CONSTRUCTION, please read EDIT.TODO */ #include #include #include #include -#include "instance.h" -#include "local.h" #include "win.h" -#include "class.h" -#include "stackframe.h" /* for MAKE_SEGPTR */ -#include "user.h" +#include "local.h" +#include "stackframe.h" #include "stddebug.h" #include "debug.h" #include "xmalloc.h" #include "callback.h" -#ifdef WINELIB32 -#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \ - SendMessage(GetParent(hWndCntrl), WM_COMMAND, \ - MAKEWPARAM(GetDlgCtrlID(hWndCntrl),wNotifyCode), \ - (LPARAM)hWndCntrl ); -#else -#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \ - SendMessage(GetParent(hWndCntrl), WM_COMMAND, \ - GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode)); -#endif +#define BUFLIMIT_MULTI 65535 /* maximum text buffer length */ +#define BUFLIMIT_SINGLE 32767 /* maximum text buffer length */ +#define BUFSTART_MULTI 1024 /* starting length for multi-line control */ +#define BUFSTART_SINGLE 256 /* starting length for single line control */ +#define GROWLENGTH 64 /* buffers grow by this much */ +#define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */ -#define MAXTEXTLEN 30000 /* maximum text buffer length */ -#define EDITLEN 1024 /* starting length for multi-line control */ -#define ENTRYLEN 256 /* starting length for single line control */ -#define GROWLENGTH 64 /* buffers grow by this much */ +typedef enum +{ + END_0 = 0, + END_DELIMIT, + END_NONE, + END_HARD, + END_SOFT, +} LINE_END; + +typedef struct { + int offset; + int length; + LINE_END ending; +} LINEDEF; typedef struct { - int wlines; /* number of lines of text */ - int wtop; /* top line that is displayed */ - int wleft; /* left pixel that is displayed */ - unsigned int textlen; /* text buffer length */ - int textwidth; /* width of longest line in pixels */ - RECT fmtrc; /* rectangle in which to format text */ - int txtht; /* height of text line in pixels */ - HANDLE hText; /* handle to text buffer */ - INT *CharWidths; /* widths of chars in font */ - unsigned int *textptrs; /* list of line offsets */ - int CurrCol; /* current column */ - int CurrLine; /* current line */ - int WndCol; /* current window column */ - int WndRow; /* current window row */ - BOOL TextChanged; /* TRUE if text has changed */ - BOOL PaintBkgd; /* paint control background */ - unsigned int MaxTextLen; /* maximum text buffer length */ - int SelBegLine; /* beginning line of selection */ - int SelBegCol; /* beginning column of selection */ - int SelEndLine; /* ending line of selection */ - int SelEndCol; /* ending column of selection */ - HFONT hFont; /* handle of current font (if not default) */ - HANDLE hDeletedText; /* handle to deleted text buffer for undo */ - int DeletedLength; /* length of deleted text */ - int DeletedCurrLine; /* starting line from which text was deleted */ - int DeletedCurrCol; /* starting col from which text was deleted */ - int NumTabStops; /* number of tab stops in buffer hTabStops */ - unsigned short *TabStops;/* tab stops buffer */ - BOOL HaveFocus; /* TRUE if this edit has the focus */ - int ClientWidth; /* computed from the window's ClientRect */ - int ClientHeight; /* ditto */ - char PasswordChar; /* The password character */ - EDITWORDBREAKPROC WordBreakProc; - int CaretPrepareCount; /* Did we already prepare the caret ? */ - BOOL CaretHidden; /* Did we hide the caret during painting ? */ - int oldWndCol; /* WndCol before we started painting */ - int oldWndRow; /* ditto for WndRow */ + int TextWidth; /* width of the widest line in pixels */ + HLOCAL hBuf; + char *text; + HFONT hFont; + LINEDEF *LineDefs; + int XOffset; /* possitive offset of the viewport in pixels */ + int FirstVisibleLine; + int LineCount; + int LineHeight; /* height of a screen line in pixels */ + int AveCharWidth; /* average character width in pixels */ + unsigned int BufLimit; + unsigned int BufSize; + BOOL TextChanged; + BOOL Redraw; + int SelStart; /* offset of selection start, == SelEnd if no selection */ + int SelEnd; /* offset of selection end == current caret position */ + int NumTabStops; + LPINT TabStops; + EDITWORDBREAKPROC WordBreakProc; + char PasswordChar; } EDITSTATE; -#define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \ - ? EDITLEN : ENTRYLEN) -#define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol) -#define SelMarked(es) (((es)->SelBegCol != (es)->SelEndCol) || \ - ((es)->SelBegLine != (es)->SelEndLine)) -#define ROUNDUP(numer, denom) (((numer) % (denom)) \ - ? ((((numer) + (denom)) / (denom)) * (denom)) \ - : (numer) + (denom)) - -/* "line" dimension for horizontal scroll */ -#define HSCROLLDIM(es) ((es)->ClientWidth / 3) +#define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0) +#define ORDER_INT(x,y) do { if ((y) < (x)) SWAP_INT((x),(y)); } while(0) /* macros to access window styles */ -#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) +#define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE) +#define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL) +#define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL) +#define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY) +#define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0) -/* internal variables */ -static BOOL TextMarking; /* TRUE if text marking in progress */ -static BOOL ButtonDown; /* TRUE if left mouse button down */ -static int ButtonRow; /* row in text buffer when button pressed */ -static int ButtonCol; /* col in text buffer when button pressed */ - -#define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0) +#define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra)) +#ifdef WINELIB32 +#define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \ + SendMessage((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \ + (WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf) +#define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \ + SendMessage((wndPtr)->parent->hwndSelf, WM_COMMAND, \ + MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \ + (LPARAM)(wndPtr)->hwndSelf ) +#define DPRINTF_EDIT_MSG(str) \ + dprintf_edit(stddeb, \ + "edit: " str ": hwnd=%08x, wParam=%08x, lParam=%08lx\n", \ + (UINT)hwnd, (UINT)wParam, (DWORD)lParam) +#else +#define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \ + SendMessage((wndPtr)->parent->hwndSelf, WM_CTLCOLOR, \ + (WPARAM)(hdc), MAKELPARAM((wndPtr)->hwndSelf, CTLCOLOR_EDIT)) +#define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \ + SendMessage((wndPtr)->parent->hwndSelf, WM_COMMAND, \ + (wndPtr)->wIDmenu, \ + MAKELPARAM((wndPtr)->hwndSelf, wNotifyCode)) +#define DPRINTF_EDIT_MSG(str) \ + dprintf_edit(stddeb, \ + "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08lx\n", \ + (UINT)hwnd, (UINT)wParam, (DWORD)lParam) +#endif /********************************************************************* - * EDIT_HeapAlloc * - * Allocate the specified number of bytes on the specified local heap. - */ -static HLOCAL EDIT_HeapAlloc(HWND hwnd, int bytes, WORD flags) -{ - HLOCAL ret; - - ret = LOCAL_Alloc( WIN_GetWindowInstance(hwnd), flags, bytes ); - if (!ret) - fprintf(stderr, "EDIT_HeapAlloc: Out of heap-memory\n"); - return ret; -} - -/********************************************************************* - * EDIT_HeapLock + * Declarations * - * Return the address of the memory pointed to by the handle. - */ -static void *EDIT_HeapLock(HWND hwnd, HANDLE handle) -{ - return LOCAL_Lock( WIN_GetWindowInstance(hwnd), handle ); -} - -/********************************************************************* - * EDIT_HeapUnlock - */ -static void EDIT_HeapUnlock(HWND hwnd, HANDLE handle) -{ - if (handle == 0) return; - LOCAL_Unlock( WIN_GetWindowInstance( hwnd ), handle ); -} - -/********************************************************************* - * EDIT_HeapReAlloc + * Files like these should really be kept in alphabetical order. * - * Reallocate the memory pointed to by the handle. */ -static HLOCAL EDIT_HeapReAlloc(HWND hwnd, HANDLE handle, int bytes) -{ - return LOCAL_ReAlloc( WIN_GetWindowInstance(hwnd), handle, bytes, - LMEM_FIXED ); -} +LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +static void EDIT_BuildLineDefs(WND *wndPtr); +static int EDIT_CallWordBreakProc(WND *wndPtr, char *s, int index, int count, int action); +static int EDIT_ColFromWndX(WND *wndPtr, int line, int x); +static void EDIT_DelEnd(WND *wndPtr); +static void EDIT_DelLeft(WND *wndPtr); +static void EDIT_DelRight(WND *wndPtr); +static int EDIT_GetAveCharWidth(WND *wndPtr); +static int EDIT_GetLineHeight(WND *wndPtr); +static void EDIT_GetLineRect(WND *wndPtr, int line, int scol, int ecol, LPRECT rc); +static char * EDIT_GetPointer(WND *wndPtr); +static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static BOOL EDIT_GetRedraw(WND *wndPtr); +static int EDIT_GetTextWidth(WND *wndPtr); +static int EDIT_GetVisibleLineCount(WND *wndPtr); +static int EDIT_GetWndWidth(WND *wndPtr); +static int EDIT_GetXOffset(WND *wndPtr); +static int EDIT_LineFromWndY(WND *wndPtr, int y); +static BOOL EDIT_MakeFit(WND *wndPtr, int size); +static void EDIT_MoveBackward(WND *wndPtr, BOOL extend); +static void EDIT_MoveDownward(WND *wndPtr, BOOL extend); +static void EDIT_MoveEnd(WND *wndPtr, BOOL extend); +static void EDIT_MoveForward(WND *wndPtr, BOOL extend); +static void EDIT_MoveHome(WND *wndPtr, BOOL extend); +static void EDIT_MovePageDown(WND *wndPtr, BOOL extend); +static void EDIT_MovePageUp(WND *wndPtr, BOOL extend); +static void EDIT_MoveUpward(WND *wndPtr, BOOL extend); +static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend); +static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend); +static void EDIT_PaintLine(WND *wndPtr, HDC hdc, int line); +static int EDIT_PaintText(WND *wndPtr, HDC hdc, int x, int y, int line, int col, int count, BOOL rev); +static void EDIT_ReleasePointer(WND *wndPtr); +static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static void EDIT_ScrollIntoView(WND *wndPtr); +static int EDIT_WndXFromCol(WND *wndPtr, int line, int col); +static int EDIT_WndYFromLine(WND *wndPtr, int line); +static int EDIT_WordBreakProc(char *s, int index, int count, int action); + +static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam); + +static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam); +static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); /********************************************************************* - * EDIT_HeapFree * - * Frees the memory pointed to by the handle. - */ -static void EDIT_HeapFree(HWND hwnd, HANDLE handle) -{ - LOCAL_Free( WIN_GetWindowInstance(hwnd), handle ); -} - - -/********************************************************************* - * EDIT_HeapSize + * EditWndProc() * - * Return the size of the given object on the local heap. */ -static unsigned int EDIT_HeapSize(HWND hwnd, HANDLE handle) +LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - return LOCAL_Size( WIN_GetWindowInstance(hwnd), handle ); + LRESULT lResult = 0L; + WND *wndPtr = WIN_FindWndPtr(hwnd); + + switch (msg) { + case EM_CANUNDO: + DPRINTF_EDIT_MSG("EM_CANUNDO"); + lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam); + break; + case EM_EMPTYUNDOBUFFER: + DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER"); + lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam); + break; + case EM_FMTLINES: + DPRINTF_EDIT_MSG("EM_FMTLINES"); + lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam); + break; + case EM_GETFIRSTVISIBLELINE: + DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE"); + lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam); + break; + case EM_GETHANDLE: + DPRINTF_EDIT_MSG("EM_GETHANDLE"); + lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam); + break; + case EM_GETLINE: + DPRINTF_EDIT_MSG("EM_GETLINE"); + lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam); + break; + case EM_GETLINECOUNT: + DPRINTF_EDIT_MSG("EM_GETLINECOUNT"); + lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam); + break; + case EM_GETMODIFY: + DPRINTF_EDIT_MSG("EM_GETMODIFY"); + lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam); + break; + case EM_GETPASSWORDCHAR: + DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR"); + lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam); + break; + case EM_GETRECT: + DPRINTF_EDIT_MSG("EM_GETRECT"); + lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam); + break; + case EM_GETSEL: + DPRINTF_EDIT_MSG("EM_GETSEL"); + lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam); + break; + case EM_GETTHUMB: + DPRINTF_EDIT_MSG("EM_GETTHUMB"); + lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam); + break; + case EM_GETWORDBREAKPROC: + DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC"); + lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam); + break; + case EM_LIMITTEXT: + DPRINTF_EDIT_MSG("EM_LIMITTEXT"); + lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam); + break; + case EM_LINEFROMCHAR: + DPRINTF_EDIT_MSG("EM_LINEFROMCHAR"); + lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam); + break; + case EM_LINEINDEX: + DPRINTF_EDIT_MSG("EM_LINEINDEX"); + lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam); + break; + case EM_LINELENGTH: + DPRINTF_EDIT_MSG("EM_LINELENGTH"); + lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam); + break; + case EM_LINESCROLL: + DPRINTF_EDIT_MSG("EM_LINESCROLL"); + lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam); + break; + case EM_REPLACESEL: + DPRINTF_EDIT_MSG("EM_REPLACESEL"); + lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam); + break; + case EM_SCROLL: + DPRINTF_EDIT_MSG("EM_SCROLL"); + lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam); + break; + case EM_SETHANDLE: + DPRINTF_EDIT_MSG("EM_SETHANDLE"); + lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam); + break; + case EM_SETMODIFY: + DPRINTF_EDIT_MSG("EM_SETMODIFY"); + lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam); + break; + case EM_SETPASSWORDCHAR: + DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR"); + lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam); + break; + case EM_SETREADONLY: + DPRINTF_EDIT_MSG("EM_SETREADONLY"); + lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam); + break; + case EM_SETRECT: + DPRINTF_EDIT_MSG("EM_SETRECT"); + lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam); + break; + case EM_SETRECTNP: + DPRINTF_EDIT_MSG("EM_SETRECTNP"); + lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam); + break; + case EM_SETSEL: + DPRINTF_EDIT_MSG("EM_SETSEL"); + lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam); + break; + case EM_SETTABSTOPS: + DPRINTF_EDIT_MSG("EM_SETTABSTOPS"); + lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam); + break; + case EM_SETWORDBREAKPROC: + DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC"); + lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam); + break; + case EM_UNDO: + case WM_UNDO: + DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO"); + lResult = EDIT_EM_Undo(wndPtr, wParam, lParam); + break; + case WM_GETDLGCODE: + DPRINTF_EDIT_MSG("WM_GETDLGCODE"); + lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam); + break; + case WM_CHAR: + DPRINTF_EDIT_MSG("WM_CHAR"); + lResult = EDIT_WM_Char(wndPtr, wParam, lParam); + break; + case WM_CLEAR: + DPRINTF_EDIT_MSG("WM_CLEAR"); + lResult = EDIT_WM_Clear(wndPtr, wParam, lParam); + break; + case WM_COPY: + DPRINTF_EDIT_MSG("WM_COPY"); + lResult = EDIT_WM_Copy(wndPtr, wParam, lParam); + break; + case WM_CREATE: + DPRINTF_EDIT_MSG("WM_CREATE"); + lResult = EDIT_WM_Create(wndPtr, wParam, lParam); + break; + case WM_CUT: + DPRINTF_EDIT_MSG("WM_CUT"); + lResult = EDIT_WM_Cut(wndPtr, wParam, lParam); + break; + case WM_DESTROY: + DPRINTF_EDIT_MSG("WM_DESTROY"); + lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam); + break; + case WM_ENABLE: + DPRINTF_EDIT_MSG("WM_ENABLE"); + lResult = EDIT_WM_Enable(wndPtr, wParam, lParam); + break; + case WM_ERASEBKGND: + DPRINTF_EDIT_MSG("WM_ERASEBKGND"); + lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam); + break; + case WM_GETFONT: + DPRINTF_EDIT_MSG("WM_GETFONT"); + lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam); + break; + case WM_GETTEXT: + DPRINTF_EDIT_MSG("WM_GETTEXT"); + lResult = EDIT_WM_GetText(wndPtr, wParam, lParam); + break; + case WM_GETTEXTLENGTH: + DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH"); + lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam); + break; + case WM_HSCROLL: + DPRINTF_EDIT_MSG("WM_HSCROLL"); + lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam); + break; + case WM_KEYDOWN: + DPRINTF_EDIT_MSG("WM_KEYDOWN"); + lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam); + break; + case WM_KILLFOCUS: + DPRINTF_EDIT_MSG("WM_KILLFOCUS"); + lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam); + break; + case WM_LBUTTONDBLCLK: + DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK"); + lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam); + break; + case WM_LBUTTONDOWN: + DPRINTF_EDIT_MSG("WM_LBUTTONDOWN"); + lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam); + break; + case WM_LBUTTONUP: + DPRINTF_EDIT_MSG("WM_LBUTTONUP"); + lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam); + break; + case WM_MOUSEMOVE: + /* + * DPRINTF_EDIT_MSG("WM_MOUSEMOVE"); + */ + lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam); + break; + case WM_PAINT: + DPRINTF_EDIT_MSG("WM_PAINT"); + lResult = EDIT_WM_Paint(wndPtr, wParam, lParam); + break; + case WM_PASTE: + DPRINTF_EDIT_MSG("WM_PASTE"); + lResult = EDIT_WM_Paste(wndPtr, wParam, lParam); + break; + case WM_SETCURSOR: + /* + * DPRINTF_EDIT_MSG("WM_SETCURSOR"); + */ + lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam); + break; + case WM_SETFOCUS: + DPRINTF_EDIT_MSG("WM_SETFOCUS"); + lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam); + break; + case WM_SETFONT: + DPRINTF_EDIT_MSG("WM_SETFONT"); + lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam); + break; + case WM_SETREDRAW: + DPRINTF_EDIT_MSG("WM_SETREDRAW"); + lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam); + break; + case WM_SETTEXT: + DPRINTF_EDIT_MSG("WM_SETTEXT"); + lResult = EDIT_WM_SetText(wndPtr, wParam, lParam); + break; + case WM_SIZE: + DPRINTF_EDIT_MSG("WM_SIZE"); + lResult = EDIT_WM_Size(wndPtr, wParam, lParam); + break; + case WM_VSCROLL: + DPRINTF_EDIT_MSG("WM_VSCROLL"); + lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam); + break; + default: + if (msg >= WM_USER) + fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg); + lResult = DefWindowProc(hwnd, msg, wParam, lParam); + break; + } + EDIT_ReleasePointer(wndPtr); + return lResult; } -/******************************************************************** - * EDIT_RecalcSize - * - * Sets the ClientWidth/ClientHeight fields of the EDITSTATE - * Called on WM_SIZE and WM_SetFont messages - */ -static void EDIT_RecalcSize(HWND hwnd, EDITSTATE *es) -{ - RECT rect; - GetClientRect(hwnd,&rect); - es->ClientWidth = rect.right > rect.left ? rect.right - rect.left : 0; - es->ClientHeight = rect.bottom > rect.top ? (rect.bottom - rect.top) / es->txtht : 0; -} /********************************************************************* - * EDIT_GetEditState - */ -static EDITSTATE *EDIT_GetEditState(HWND hwnd) -{ - return (EDITSTATE *)GetWindowLong(hwnd,0); -} - -/********************************************************************* - * EDIT_CaretPrepare * - * Save the caret state before any painting is done. + * EDIT_BuildLineDefs + * + * Build array of pointers to text lines. + * Lines can end with '\0' (last line), nothing (if it is to long), + * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n' + * */ -static void EDIT_CaretPrepare(HWND hwnd) +static void EDIT_BuildLineDefs(WND *wndPtr) { - EDITSTATE *es = EDIT_GetEditState(hwnd); + EDITSTATE *es = EDITSTATEPTR(wndPtr); + char *text = EDIT_GetPointer(wndPtr); + int ww = EDIT_GetWndWidth(wndPtr); + HDC hdc; + HFONT hFont; + HFONT oldFont = 0; + char *start, *cp; + int prev, next; + int width; + int length; + LINE_END ending; - if (!es) return; + hdc = GetDC(wndPtr->hwndSelf); + hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L); + if (hFont) + oldFont = SelectObject(hdc, hFont); - if (!es->CaretPrepareCount) - { - es->CaretHidden = FALSE; - es->oldWndCol = es->WndCol; - es->oldWndRow = es->WndRow; - } + if (!IsMultiLine(wndPtr)) { + es->LineCount = 1; + es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF)); + es->LineDefs[0].offset = 0; + es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L); + es->LineDefs[0].ending = END_0; + es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text, + es->LineDefs[0].length, + es->NumTabStops, es->TabStops)); + } else { + es->LineCount = 0; + start = text; + do { + if (!(cp = strstr(start, "\r\n"))) { + ending = END_0; + length = strlen(start); + } else if ((cp > start) && (*(cp - 1) == '\r')) { + ending = END_SOFT; + length = cp - start - 1; + } else { + ending = END_HARD; + length = cp - start; + } + width = LOWORD(GetTabbedTextExtent(hdc, start, length, + es->NumTabStops, es->TabStops)); - es->CaretPrepareCount++; + if (IsWordWrap(wndPtr) && (width > ww)) { + next = 0; + do { + prev = next; + next = EDIT_CallWordBreakProc(wndPtr, start, + prev + 1, length, WB_RIGHT); + width = LOWORD(GetTabbedTextExtent(hdc, start, next, + es->NumTabStops, es->TabStops)); + } while (width <= ww); + if (prev) { + length = prev; + if (EDIT_CallWordBreakProc(wndPtr, start, length - 1, + length, WB_ISDELIMITER)) { + length--; + ending = END_DELIMIT; + } else + ending = END_NONE; + } else { + } + width = LOWORD(GetTabbedTextExtent(hdc, start, length, + es->NumTabStops, es->TabStops)); + } + + es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF)); + es->LineDefs[es->LineCount].offset = start - text; + es->LineDefs[es->LineCount].length = length; + es->LineDefs[es->LineCount].ending = ending; + es->LineCount++; + es->TextWidth = MAX(es->TextWidth, width); + + start += length; + switch (ending) { + case END_SOFT: + start += 3; + break; + case END_HARD: + start += 2; + break; + case END_DELIMIT: + start++; + break; + default: + break; + } + } while (*start || (ending == END_SOFT) || (ending == END_HARD)); + } + if (hFont) + SelectObject(hdc, oldFont); + ReleaseDC(wndPtr->hwndSelf, hdc); } -/********************************************************************* - * EDIT_CaretHide - * - * Called before some painting is done. - */ -static void EDIT_CaretHide(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - if (!es) return; - if (!es->HaveFocus) return; - if (!es->CaretPrepareCount) return; - - if (!es->CaretHidden) - { - HideCaret(hwnd); - es->CaretHidden = TRUE; - } +/********************************************************************* + * + * EDIT_CallWordBreakProc + * + * Call appropriate WordBreakProc (internal or external). + * + */ +static int EDIT_CallWordBreakProc(WND *wndPtr, char *s, int index, int count, int action) +{ + EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L); + + if (wbp) { + return CallWordBreakProc((FARPROC)wbp, + (LONG)MAKE_SEGPTR(s), index, count, action); + } else + return EDIT_WordBreakProc(s, index, count, action); } + /********************************************************************* - * EDIT_CaretUpdate * - * Called after all painting is done. + * EDIT_ColFromWndX + * + * Calculates, for a given line and X-coordinate on the screen, the column. + * */ -static void EDIT_CaretUpdate(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); +static int EDIT_ColFromWndX(WND *wndPtr, int line, int x) +{ + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, lineindex, 0L); + int i; - if (!es) return; - if (!es->CaretPrepareCount) return; - - es->CaretPrepareCount--; - - if (es->CaretPrepareCount) return; - if (!es->HaveFocus) return; - - if ((es->WndCol != es->oldWndCol) || (es->WndRow != es->oldWndRow)) - SetCaretPos(es->WndCol, es->WndRow * es->txtht); - - if (es->CaretHidden) - { - ShowCaret(hwnd); - es->CaretHidden = FALSE; - } + line = MAX(0, MIN(line, linecount - 1)); + for (i = 0 ; i < linelength ; i++) + if (EDIT_WndXFromCol(wndPtr, line, i) >= x) + break; + return i; } + /********************************************************************* - * 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. + * EDIT_DelEnd + * + * Delete all characters on this line to right of cursor. + * + */ +static void EDIT_DelEnd(WND *wndPtr) +{ + EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0)); + EDIT_MoveEnd(wndPtr, TRUE); + EDIT_WM_Clear(wndPtr, 0, 0L); +} + + +/********************************************************************* + * + * EDIT_DelLeft + * + * Delete character to left of cursor. + * + */ +static void EDIT_DelLeft(WND *wndPtr) +{ + EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0)); + EDIT_MoveBackward(wndPtr, TRUE); + EDIT_WM_Clear(wndPtr, 0, 0L); +} + + +/********************************************************************* + * + * EDIT_DelRight + * + * Delete character to right of cursor. + * + */ +static void EDIT_DelRight(WND *wndPtr) +{ + EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0)); + EDIT_MoveForward(wndPtr, TRUE); + EDIT_WM_Clear(wndPtr, 0, 0L); +} + + +/********************************************************************* + * + * EDIT_GetAveCharWidth + * + */ +static int EDIT_GetAveCharWidth(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return es->AveCharWidth; +} + + +/********************************************************************* + * + * EDIT_GetLineHeight + * + */ +static int EDIT_GetLineHeight(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return es->LineHeight; +} + + +/********************************************************************* + * + * EDIT_GetLineRect + * + * Calculates the bounding rectangle for a line from a starting + * column to an ending column. + * + */ +static void EDIT_GetLineRect(WND *wndPtr, int line, int scol, int ecol, LPRECT rc) +{ + rc->top = EDIT_WndYFromLine(wndPtr, line); + rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr); + rc->left = EDIT_WndXFromCol(wndPtr, line, scol); + rc->right = (ecol < 0) ? EDIT_GetWndWidth(wndPtr) : EDIT_WndXFromCol(wndPtr, line, ecol); +} + + +/********************************************************************* + * + * EDIT_GetPointer + * + * This acts as a LOCAL_Lock(), but it locks only once. This way + * you can call it whenever you like, without unlocking. + * + */ +static char *EDIT_GetPointer(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + if (!es->text && es->hBuf) + es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf); + return es->text; +} + + +/********************************************************************* + * + * EDIT_GetRect + * + * Beware: This is not the function called on EM_GETRECT. + * It expects a (LPRECT) in lParam, not a (SEGPTR). + * It is used internally, as if there were no pointer difficulties. + * + */ +static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + GetClientRect(wndPtr->hwndSelf, (LPRECT)lParam); + return 0L; +} + + +/********************************************************************* + * + * EDIT_GetRedraw + * + */ +static BOOL EDIT_GetRedraw(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return es->Redraw; +} + + +/********************************************************************* + * + * EDIT_GetTextWidth + * + */ +static int EDIT_GetTextWidth(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return es->TextWidth; +} + + +/********************************************************************* + * + * EDIT_GetVisibleLineCount + * + */ +static int EDIT_GetVisibleLineCount(WND *wndPtr) +{ + RECT rc; + + EDIT_GetRect(wndPtr, 0, (LPARAM)&rc); + return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr)); +} + + +/********************************************************************* + * + * EDIT_GetWndWidth + * + */ +static int EDIT_GetWndWidth(WND *wndPtr) +{ + RECT rc; + + EDIT_GetRect(wndPtr, 0, (LPARAM)&rc); + return rc.right - rc.left; +} + + +/********************************************************************* + * + * EDIT_GetXOffset + * + */ +static int EDIT_GetXOffset(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return es->XOffset; +} + + +/********************************************************************* + * + * EDIT_LineFromWndY + * + * Calculates, for a given Y-coordinate on the screen, the line. + * + */ +static int EDIT_LineFromWndY(WND *wndPtr, int y) +{ + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + int lineheight = EDIT_GetLineHeight(wndPtr); + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); + + return MAX(0, MIN(linecount - 1, y / lineheight + firstvis)); +} + + +/********************************************************************* + * + * EDIT_MakeFit + * + * Try to fit size + 1 bytes in the buffer. Contrain to limits. + * + */ +static BOOL EDIT_MakeFit(WND *wndPtr, int size) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + if (size <= es->BufSize) + return TRUE; + if (size > es->BufLimit) + return FALSE; + es->BufSize = ((size / GROWLENGTH) + 1) * GROWLENGTH; + if (es->BufSize > es->BufLimit) + es->BufSize = es->BufLimit; + + dprintf_edit(stddeb, "edit: EDIT_MakeFit: ReAlloc to %d+1\n", es->BufSize); + + return LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, es->BufSize + 1, LMEM_MOVEABLE); +} + + +/********************************************************************* + * + * EDIT_MoveBackward + * + */ +static void EDIT_MoveBackward(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + + if (e - lineindex == 0) { + if (l) { + lineindex = EDIT_EM_LineIndex(wndPtr, l - 1, 0L); + e = lineindex + EDIT_EM_LineLength(wndPtr, lineindex, 0L); + } + } else + e--; + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveDownward + * + */ +static void EDIT_MoveDownward(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + int x; + + if (l < linecount - 1) { + x = EDIT_WndXFromCol(wndPtr, l, e - lineindex); + l++; + e = EDIT_EM_LineIndex(wndPtr, l, 0L) + + EDIT_ColFromWndX(wndPtr, l, x); + } + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveEnd + * + */ +static void EDIT_MoveEnd(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + + e = lineindex + linelength; + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveForward + * + */ +static void EDIT_MoveForward(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + + if (e - lineindex == linelength) { + if (l != linecount - 1) + e = EDIT_EM_LineIndex(wndPtr, l + 1, 0L); + } else + e++; + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveHome + * + * Home key: move to beginning of line. + * + */ +static void EDIT_MoveHome(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + + e = lineindex; + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MovePageDown + * + */ +static void EDIT_MovePageDown(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + int x; + + if (l < linecount - 1) { + x = EDIT_WndXFromCol(wndPtr, l, e - lineindex); + l = MIN(linecount - 1, l + EDIT_GetVisibleLineCount(wndPtr)); + e = EDIT_EM_LineIndex(wndPtr, l, 0L) + + EDIT_ColFromWndX(wndPtr, l, x); + } + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MovePageUp + * + */ +static void EDIT_MovePageUp(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + int x; + + if (l) { + x = EDIT_WndXFromCol(wndPtr, l, e - lineindex); + l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr)); + e = EDIT_EM_LineIndex(wndPtr, l, 0L) + + EDIT_ColFromWndX(wndPtr, l, x); + } + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveUpward + * + */ +static void EDIT_MoveUpward(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + int x; + + if (l) { + x = EDIT_WndXFromCol(wndPtr, l, e - lineindex); + l--; + e = EDIT_EM_LineIndex(wndPtr, l, 0L) + + EDIT_ColFromWndX(wndPtr, l, x); + } + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveWordBackward + * + */ +static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + char *text; + + if (e - lineindex == 0) { + if (l) { + lineindex = EDIT_EM_LineIndex(wndPtr, l - 1, 0L); + e = lineindex + EDIT_EM_LineLength(wndPtr, lineindex, 0L); + } + } else { + text = EDIT_GetPointer(wndPtr); + e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex, + e - lineindex, linelength, WB_LEFT); + } + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_MoveWordForward + * + */ +static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + char *text; + + if (e - lineindex == linelength) { + if (l != linecount - 1) + e = EDIT_EM_LineIndex(wndPtr, l + 1, 0L); + } else { + text = EDIT_GetPointer(wndPtr); + e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex, + e - lineindex + 1, linelength, WB_RIGHT); + } + if (!extend) + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); +} + + +/********************************************************************* + * + * EDIT_PaintLine + * + */ +static void EDIT_PaintLine(WND *wndPtr, HDC hdc, int line) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + int viscount = EDIT_GetVisibleLineCount(wndPtr); + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); + int LineStart; + int LineEnd; + int ReverseStart; + int ReverseEnd; + int x; + int y; + + if ((line < firstvis) || (line > firstvis + viscount) || (line >= linecount)) + return; + + dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line); + + x = EDIT_WndXFromCol(wndPtr, line, 0); + y = EDIT_WndYFromLine(wndPtr, line); + LineStart = EDIT_EM_LineIndex(wndPtr, line, 0L); + LineEnd = LineStart + EDIT_EM_LineLength(wndPtr, LineStart, 0L); + ReverseStart = MIN(es->SelStart, es->SelEnd); + ReverseEnd = MAX(es->SelStart, es->SelEnd); + ReverseStart = MIN(LineEnd, MAX(LineStart, ReverseStart)); + ReverseEnd = MIN(LineEnd, MAX(LineStart, ReverseEnd)); + if (ReverseStart != ReverseEnd) { + x += EDIT_PaintText(wndPtr, hdc, x, y, line, + 0, ReverseStart - LineStart, FALSE); + x += EDIT_PaintText(wndPtr, hdc, x, y, line, + ReverseStart - LineStart, + ReverseEnd - ReverseStart, TRUE); + x += EDIT_PaintText(wndPtr, hdc, x, y, line, + ReverseEnd - LineStart, + LineEnd - ReverseEnd, FALSE); + } else + x += EDIT_PaintText(wndPtr, hdc, x, y, line, + 0, LineEnd - LineStart, FALSE); +} + + +/********************************************************************* + * + * EDIT_PaintText + * + */ +static int EDIT_PaintText(WND *wndPtr, HDC hdc, int x, int y, int line, int col, int count, BOOL rev) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + COLORREF BkColor; + COLORREF TextColor; + int ret; + char *text; + int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L); + int xoffset = EDIT_GetXOffset(wndPtr); + + if (count < 1) + return 0; + + BkColor = GetBkColor(hdc); + TextColor = GetTextColor(hdc); + if (rev) { + SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + text = EDIT_GetPointer(wndPtr); + ret = LOWORD(TabbedTextOut(hdc, x, y, text + lineindex + col, count, + es->NumTabStops, es->TabStops, -xoffset)); + if (rev) { + SetBkColor(hdc, BkColor); + SetTextColor(hdc, TextColor); + } + return ret; +} + + +/********************************************************************* + * + * EDIT_ReleasePointer + * + * This is the only helper function that can be called with es = NULL. + * It is called at the end of EditWndProc() to unlock the buffer. + * + */ +static void EDIT_ReleasePointer(WND *wndPtr) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + if (!es) + return; + if (es->text && es->hBuf) + LOCAL_Unlock(wndPtr->hInstance, es->hBuf); + es->text = NULL; +} + + +/********************************************************************* + * + * EDIT_ReplaceSel + * + * Beware: This is not the function called on EM_REPLACESEL. + * It expects a (char *) in lParam, not a (SEGPTR). + * It is used internally, as if there were no pointer difficulties. + * + */ +static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + const char *str = (char *)lParam; + int strl = strlen(str); + int tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L); + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int i; + char *p; + char *text; + BOOL redraw; + + ORDER_INT(s,e); + if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) { + EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT); + return 0L; + } + redraw = EDIT_GetRedraw(wndPtr); + EDIT_WM_SetRedraw(wndPtr, FALSE, 0L); + EDIT_WM_Clear(wndPtr, 0, 0L); + tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L); + e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + text = EDIT_GetPointer(wndPtr); + for (p = text + tl ; p >= text + e ; p--) + p[strl] = p[0]; + for (i = 0 , p = text + e ; i < strl ; i++) + p[i] = str[i]; + EDIT_BuildLineDefs(wndPtr); + e += strl; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(e, e)); + EDIT_EM_SetModify(wndPtr, TRUE, 0L); + EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE); + EDIT_WM_SetRedraw(wndPtr, redraw, 0L); + if (redraw) { + InvalidateRect(wndPtr->hwndSelf, NULL, TRUE); + EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE); + } + return 0L; +} + + +/********************************************************************* + * + * EDIT_ScrollIntoView + * + * Makes sure the caret is visible. + * + */ +static void EDIT_ScrollIntoView(WND *wndPtr) +{ + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + int vislinecount = EDIT_GetVisibleLineCount(wndPtr); + int wndwidth = EDIT_GetWndWidth(wndPtr); + int charwidth = EDIT_GetAveCharWidth(wndPtr); + int x = EDIT_WndXFromCol(wndPtr, l, e - lineindex); + int dy = 0; + int dx = 0; + + if (l >= firstvis + vislinecount) + dy = l - vislinecount + 1 - firstvis; + if (l < firstvis) + dy = l - firstvis; + if (x < 0) + dx = x - wndwidth / HSCROLL_FRACTION / charwidth * charwidth; + if (x > wndwidth) + dx = x - (HSCROLL_FRACTION - 1) * wndwidth / HSCROLL_FRACTION / charwidth * charwidth; + if (dy || dx) { + EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx)); + if (dy) + EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL); + if (dx) + EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL); + } +} + + +/********************************************************************* + * + * EDIT_WndXFromCol + * + * Calculates, for a given line and column, the X-coordinate on the screen. + * + */ +static int EDIT_WndXFromCol(WND *wndPtr, int line, int col) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + char *text = EDIT_GetPointer(wndPtr); + int ret; + HDC hdc; + HFONT hFont; + HFONT oldFont = 0; + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, lineindex, 0L); + int xoffset = EDIT_GetXOffset(wndPtr); + + hdc = GetDC(wndPtr->hwndSelf); + hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L); + if (hFont) + oldFont = SelectObject(hdc, hFont); + line = MAX(0, MIN(line, linecount - 1)); + col = MAX(0, MIN(col, linelength)); + ret = LOWORD(GetTabbedTextExtent(hdc, + text + lineindex, col, + es->NumTabStops, es->TabStops)) - xoffset; + if (hFont) + SelectObject(hdc, oldFont); + ReleaseDC(wndPtr->hwndSelf, hdc); + return ret; +} + + +/********************************************************************* + * + * EDIT_WndYFromLine + * + * Calculates, for a given line, the Y-coordinate on the screen. + * + */ +static int EDIT_WndYFromLine(WND *wndPtr, int line) +{ + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + int lineheight = EDIT_GetLineHeight(wndPtr); + + return (line - firstvis) * lineheight; +} + + +/********************************************************************* + * + * 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 EDIT_WordBreakProc(char *s, int index, int count, int action) { - int ret = 0; + int ret = 0; - dprintf_edit(stddeb, "EDIT_WordBreakProc: s=%p, index=%d" - ", count=%d, action=%d\n", s, index, count, action); + dprintf_edit(stddeb, "edit: 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; -} - -/********************************************************************* - * EDIT_CallWordBreakProc - * - * Call appropriate WordBreakProc (internal or external). - */ -static int CALLBACK EDIT_CallWordBreakProc(HWND hwnd, char *pch, - int ichCurrent, int cch, int code) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (es->WordBreakProc) { - /* FIXME: do some stuff to make pch a SEGPTR */ - return CallWordBreakProc((FARPROC)es->WordBreakProc, (LONG)pch, ichCurrent, cch, code); - } else return EDIT_WordBreakProc(pch, ichCurrent, cch, code); -} - -/********************************************************************* - * EDIT_GetNextTabStop - * - * Return the next tab stop beyond _pcol_. - */ -static int EDIT_GetNextTabStop(HWND hwnd, int pcol) -{ - int i; - int baseUnitWidth = LOWORD(GetDialogBaseUnits()); - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (es->NumTabStops == 0) - return ROUNDUP(pcol, 8 * baseUnitWidth); - if (es->NumTabStops == 1) - return ROUNDUP(pcol, es->TabStops[0] * baseUnitWidth / 4); - for (i = 0; i < es->NumTabStops; i++) - { - if (es->TabStops[i] * baseUnitWidth / 4 >= pcol) - return es->TabStops[i] * baseUnitWidth / 4; - } - return pcol; -} - -/********************************************************************* - * EDIT_CharWidth - * - * Return the width of the given character in pixels. - * The current column offset in pixels _pcol_ is required to calculate - * the width of a tab. - */ -static int EDIT_CharWidth(HWND hwnd, short ch, int pcol) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (ch == VK_TAB) return EDIT_GetNextTabStop(hwnd, pcol) - pcol; - return es->CharWidths[ch]; -} - -/********************************************************************* - * EDIT_ClearTextPointers - * - * Clear and initialize text line pointer array. - */ -static void EDIT_ClearTextPointers(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - dprintf_edit( stddeb, "EDIT_ClearTextPointers\n" ); - es->textptrs = xrealloc(es->textptrs, sizeof(int)); - es->textptrs[0] = 0; -} - -/********************************************************************* - * EDIT_BuildTextPointers - * - * Build array of pointers to text lines. - */ -static void EDIT_BuildTextPointers(HWND hwnd) -{ - char *text, *cp; - unsigned int off, len, line; - EDITSTATE *es; - - es = EDIT_GetEditState(hwnd); - text = EDIT_HeapLock(hwnd, es->hText); - - es->textwidth = 0; - if (IsMultiLine(hwnd)) { - es->wlines = 0; - cp = text; - while ((cp = strchr(cp,'\n')) != NULL) { - es->wlines++; cp++; - } - } else es->wlines = 1; - - dprintf_edit( stddeb, "EDIT_BuildTextPointers: realloc\n" ); - es->textptrs = xrealloc(es->textptrs, (es->wlines + 2) * sizeof(int)); - - cp = text; - dprintf_edit(stddeb,"BuildTextPointers: %d lines, pointer %p\n", - es->wlines, es->textptrs); - - /* advance through text buffer */ - line = 0; - while (*cp) - { - off = cp - text; /* offset of beginning of line */ - dprintf_edit(stddeb,"BuildTextPointers: line %d offs %d\n", line, off); - es->textptrs[line] = off; - line++; - len = 0; - - /* advance through current line */ - while (*cp && *cp != '\n') - { - len += EDIT_CharWidth(hwnd, (BYTE)*cp, len); - /* width of line in pixels */ - cp++; - } - es->textwidth = MAX(es->textwidth, len); - if (*cp) - cp++; /* skip '\n' */ - } - off = cp - text; - es->textptrs[line] = off; - EDIT_HeapUnlock(hwnd, es->hText); -} - -/********************************************************************* - * EDIT_ModTextPointers - * - * Modify text pointers from a specified position. - */ -static void EDIT_ModTextPointers(HWND hwnd, int lineno, int var) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - for(;lineno < es->wlines; lineno++) es->textptrs[lineno] += var; -} - -/********************************************************************* - * EDIT_TextLine - * - * Return a pointer to the text in the specified line. - */ -static char *EDIT_TextLine(HWND hwnd, int sel) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - char *text = EDIT_HeapLock(hwnd, es->hText); - - if (sel > es->wlines) return NULL; - dprintf_edit(stddeb,"EDIT_TextLine: text %p, line %d offs %d\n", - text, sel, es->textptrs[sel]); - return text + es->textptrs[sel]; -} - -/********************************************************************* - * EDIT_GetTextLine - * - * Get a copy of the text in the specified line. - */ -static char *EDIT_GetTextLine(HWND hwnd, int selection) -{ - int len; - char *cp, *cp1; - - dprintf_edit(stddeb,"GetTextLine %d\n", selection); - cp1 = EDIT_TextLine(hwnd, selection); - - /* Find end of line */ - cp = strchr( cp1, '\r' ); - if (cp == NULL) len = strlen(cp1); - else len = cp - cp1; - - /* store selected line and return handle */ - cp = xmalloc( len + 1 ); - strncpy( cp, cp1, len); - cp[len] = 0; - return cp; -} - -/********************************************************************* - * EDIT_StrWidth - * - * Return length of string _str_ of length _len_ characters in pixels. - * The current column offset in pixels _pcol_ is required to calculate - * the width of a tab. - */ -static int EDIT_StrWidth(HWND hwnd, unsigned char *str, int len, int pcol) -{ - int i, plen = 0; - - for (i = 0; i < len; i++) - plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen); - - dprintf_edit(stddeb,"EDIT_StrWidth: returning %d, len=%d\n", plen,len); - return plen; -} - -/********************************************************************* - * EDIT_LineLength - * - * Return length of line _num_ in characters. - */ -static int EDIT_LineLength(HWND hwnd, int num) -{ - char *cp = EDIT_TextLine(hwnd, num); - char *cp1; - - if(!cp)return 0; - cp1 = strchr(cp, '\r'); - return cp1 ? (cp1 - cp) : strlen(cp); -} - -/********************************************************************* - * EDIT_GetStr - * - * Return sub-string starting at pixel _off_ of length _len_ pixels. - * If _off_ is part way through a character, the negative offset of - * the beginning of the character is returned in _diff_, else _diff_ - * will be zero. - */ -static HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff) -{ - HANDLE hStr; - char *str; - int ch = 0, i = 0, j, s_i=0; - int ch1; - - dprintf_edit(stddeb,"EDIT_GetStr lp='%s' off=%d len=%d\n", lp, off, len); - - if (off < 0) off = 0; - while (i < off) - { - s_i = i; - i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i); - ch++; - } - /* if stepped past _off_, go back a character */ - if (i > off) - { - i = s_i; - ch--; - } - *diff = off - i; - ch1 = ch; - while (i < len + off) - { - if (*(lp + ch) == '\r' || *(lp + ch) == '\n') - break; - i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i); - ch++; - } - - hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3, LMEM_FIXED); - str = (char *)EDIT_HeapLock(hwnd, hStr); - for (i = ch1, j = 0; i < ch; i++, j++) - str[j] = lp[i]; - str[j] = '\0'; - dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str); - return hStr; -} - -/********************************************************************* - * EDIT_WriteText - * - * Write text to a window - * lp - text line - * off - offset in text line (in pixels) - * len - length from off (in pixels) - * row - line in window - * col - column in window - * rc - rectangle in which to display line - * blank - blank remainder of line? - * reverse - reverse color of line? - */ -static void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, - int col, RECT *rc, BOOL blank, BOOL reverse) -{ - HDC hdc; - HANDLE hStr; - char *str, *cp, *cp1; - int diff=0, tabwidth, scol; - HRGN hrgnClip; - COLORREF oldTextColor, oldBkgdColor; - HFONT oldfont; - EDITSTATE *es = EDIT_GetEditState(hwnd); - RECT rc2; - - dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse); - - EDIT_CaretHide(hwnd); - - if( off < 0 ) { - len += off; - col -= off; - off = 0; - } - - hdc = GetDC(hwnd); - hStr = EDIT_GetStr(hwnd, lp, off, len, &diff); - str = (char *)EDIT_HeapLock(hwnd, hStr); - hrgnClip = CreateRectRgnIndirect(rc); - SelectClipRgn(hdc, hrgnClip); - DeleteObject(hrgnClip); - - if (es->hFont) - oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont); - else - oldfont = 0; /* -Wall does not see the use of if */ - -#ifdef WINELIB32 - SendMessage(GetParent(hwnd), WM_CTLCOLOREDIT, (WPARAM)hdc, (LPARAM)hwnd); -#else - SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WPARAM)hdc, - MAKELPARAM(hwnd, CTLCOLOR_EDIT)); -#endif - - if (reverse) - { - oldBkgdColor = GetBkColor(hdc); - oldTextColor = GetTextColor(hdc); - SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); - SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); - } - else /* -Wall does not see the use of if */ - oldTextColor = oldBkgdColor = 0; - - if ((es->PasswordChar && GetWindowLong( hwnd, GWL_STYLE ) & ES_PASSWORD)) - { - int len = strlen(str); - char *buff = xmalloc( len+1 ); - memset( buff, es->PasswordChar, len ); - buff[len] = '\0'; - TextOut( hdc, col - diff, row * es->txtht, buff, len ); - } - else if (!(cp = strchr(str, VK_TAB))) - TextOut(hdc, col - diff, row * es->txtht, str, strlen(str)); - else - { - TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str)); - scol = EDIT_StrWidth(hwnd, str, (int)(cp - str), 0); - tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol); - SetRect(&rc2, scol, row * es->txtht, scol+tabwidth, (row + 1) * es->txtht); - ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc2, "", 0, NULL); - cp++; - scol += tabwidth; - - while ((cp1 = strchr(cp, VK_TAB))) - { - TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp)); - scol += EDIT_StrWidth(hwnd, cp, (int)(cp1 - cp), scol); - tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol); - SetRect(&rc2, scol, row * es->txtht, scol+tabwidth, (row + 1) * es->txtht); - ExtTextOut( hdc, 0, 0, ETO_OPAQUE, &rc2, "", 0, NULL ); - cp = ++cp1; - scol += tabwidth; - } - - TextOut(hdc, scol, row * es->txtht, cp, strlen(cp)); - } - - if (reverse) - { - SetBkColor(hdc, oldBkgdColor); - SetTextColor(hdc, oldTextColor); - } - - /* blank out remainder of line if appropriate */ - if (blank && ((rc->right - col) > len)) - { - SetRect( &rc2, col + len, row * es->txtht, - rc->right, (row + 1) * es->txtht ); - ExtTextOut( hdc, 0, 0, ETO_OPAQUE, &rc2, "", 0, NULL ); - } - - if (es->hFont) - SelectObject(hdc, (HANDLE)oldfont); - - EDIT_HeapFree(hwnd, hStr); - ReleaseDC(hwnd, hdc); -} - -/********************************************************************* - * EDIT_WriteTextLine - * - * Write the line of text at offset _y_ in text buffer to a window. - */ -static void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y) -{ - int len = 0; - unsigned char *lp; - int lnlen, lnlen1; - int col, off = 0; - int sbl, sel, sbc, sec; - RECT rc; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - /* initialize rectangle if NULL, else copy */ - if (rect) - CopyRect(&rc, rect); - else - GetClientRect(hwnd, &rc); - - dprintf_edit(stddeb,"WriteTextLine %d\n", y); - - /* make sure y is inside the window */ - if (y < es->wtop || y > (es->wtop + es->ClientHeight)) - { - dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y); - return; - } - - /* make sure rectangle is within window */ - if (rc.left >= es->ClientWidth - 1) - { - dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n", - rc.left); - return; - } - if (rc.right <= 0) - { - dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n", - rc.right); - return; - } - if (y - es->wtop < (rc.top / es->txtht) || - y - es->wtop > (rc.bottom / es->txtht)) - { - dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y); - return; - } - - /* get the text and length of line */ - lp = EDIT_GetTextLine( hwnd, y ); - if (lp == NULL) return; - - lnlen = EDIT_StrWidth( hwnd, lp, strlen(lp), 0 ); - lnlen1 = lnlen; - - /* build the line to display */ - if (lnlen < (es->wleft + rc.left)) - { - lnlen = 0; - return; - } - else - { - off += es->wleft; - lnlen -= off; - } - - if (lnlen > rc.left) - { - off += rc.left; - lnlen = lnlen1 - off; - } - len = MIN(lnlen, rc.right - rc.left); - - if (SelMarked(es) && (es->HaveFocus)) - { - sbl = es->SelBegLine; - sel = es->SelEndLine; - sbc = es->SelBegCol; - sec = es->SelEndCol; - - /* put lowest marker first */ - if (sbl > sel) - { - SWAP_INT(sbl, sel); - SWAP_INT(sbc, sec); - } - if (sbl == sel && sbc > sec) - SWAP_INT(sbc, sec); - - if (y < sbl || y > sel) - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc, - TRUE, FALSE); - else if (y > sbl && y < sel) - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc, - TRUE, TRUE); - else if (y == sbl) - { - col = EDIT_StrWidth(hwnd, lp, sbc, 0); - if (col > (es->wleft + rc.left)) - { - len = MIN(col - off, rc.right - off); - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - rc.left, &rc, FALSE, FALSE); - off = col; - } - if (y == sel) - { - col = EDIT_StrWidth(hwnd, lp, sec, 0); - if (col < (es->wleft + rc.right)) - { - len = MIN(col - off, rc.right - off); - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - off - es->wleft, &rc, FALSE, TRUE); - off = col; - len = MIN(lnlen - off, rc.right - off); - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - off - es->wleft, &rc, TRUE, FALSE); + 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++; } - else - { - len = MIN(lnlen - off, rc.right - off); - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - off - es->wleft, &rc, TRUE, TRUE); - } - } - else - { - len = MIN(lnlen - off, rc.right - off); - if (col < (es->wleft + rc.right)) - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - off - es->wleft, &rc, TRUE, TRUE); - } - } - else if (y == sel) - { - col = EDIT_StrWidth(hwnd, lp, sec, 0); - if (col < (es->wleft + rc.right)) - { - len = MIN(col - off, rc.right - off); - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - off - es->wleft, &rc, FALSE, TRUE); - off = col; - len = MIN(lnlen - off, rc.right - off); - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, - off - es->wleft, &rc, TRUE, FALSE); - } - } - } - else - EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc, - TRUE, FALSE); - - free( lp ); -} - -/********************************************************************* - * EDIT_ComputeVScrollPos - * - * Compute the vertical scroll bar position from the window - * position and text width. - */ -static int EDIT_ComputeVScrollPos(HWND hwnd) -{ - int vscrollpos; - INT minpos, maxpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos); - - if (es->wlines > es->ClientHeight) - vscrollpos = (double)(es->wtop) / (double)(es->wlines - - es->ClientHeight) * (maxpos - minpos); - else - vscrollpos = minpos; - - return vscrollpos; -} - -/********************************************************************* - * EDIT_ComputeHScrollPos - * - * Compute the horizontal scroll bar position from the window - * position and text width. - */ -static int EDIT_ComputeHScrollPos(HWND hwnd) -{ - int hscrollpos; - INT minpos, maxpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos); - - if (es->textwidth > es->ClientWidth) - hscrollpos = (double)(es->wleft) / (double)(es->textwidth - - es->ClientWidth) * (maxpos - minpos); - else - hscrollpos = minpos; - - return hscrollpos; -} - -/********************************************************************* - * EDIT_KeyHScroll - * - * Scroll text horizontally using cursor keys. - */ -static void EDIT_KeyHScroll(HWND hwnd, WORD opt) -{ - int hscrollpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (opt == SB_LINEDOWN) - { - es->wleft += HSCROLLDIM(es); - es->WndCol -= HSCROLLDIM(es); - } - else - { - if (es->wleft == 0) - return; - if (es->wleft - HSCROLLDIM(es) < 0) - { - es->WndCol += es->wleft; - es->wleft = 0; - } - else - { - es->wleft -= HSCROLLDIM(es); - es->WndCol += HSCROLLDIM(es); - } - } - - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); - - if (IsHScrollBar(hwnd)) - { - hscrollpos = EDIT_ComputeHScrollPos(hwnd); - SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE); - } -} - -/********************************************************************* - * EDIT_KeyVScrollLine - * - * Scroll text vertically by one line using keyboard. - */ -static void EDIT_KeyVScrollLine(HWND hwnd, WORD opt) -{ - RECT rc; - int y, vscrollpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (!IsMultiLine(hwnd)) - return; - - if (opt == SB_LINEDOWN) - { - /* move down one line */ - if (es->wtop + es->ClientHeight >= es->wlines) - return; - es->wtop++; - } - else - { - /* move up one line */ - if (es->wtop == 0) - return; - --es->wtop; - } - - if (IsWindowVisible(hwnd)) - { - EDIT_CaretHide(hwnd); - - /* adjust client bottom to nearest whole line */ - GetClientRect(hwnd, &rc); - rc.bottom = (rc.bottom / es->txtht) * es->txtht; - - if (opt == SB_LINEUP) - { - /* move up one line (scroll window down) */ - ScrollWindow(hwnd, 0, es->txtht, &rc, &rc); - /* write top line */ - EDIT_WriteTextLine(hwnd, NULL, es->wtop); - es->WndRow++; - } - else - { - /* move down one line (scroll window up) */ - ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc); - /* write bottom line */ - y = (((rc.bottom - rc.top) / es->txtht) - 1); - EDIT_WriteTextLine(hwnd, NULL, es->wtop + y); - --es->WndRow; - } - } - - /* reset the vertical scroll bar */ - if (IsVScrollBar(hwnd)) - { - vscrollpos = EDIT_ComputeVScrollPos(hwnd); - SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE); - } -} - -/********************************************************************* - * EDIT_End - * - * End key: move to end of line. - */ -static void EDIT_End(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - while (*CurrChar && *CurrChar != '\r') - { - es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft); - es->CurrCol++; - } - - if (es->WndCol >= es->ClientWidth) - { - es->wleft = es->WndCol - es->ClientWidth + HSCROLLDIM(es); - es->WndCol -= es->wleft; - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); - } -} - -/********************************************************************* - * EDIT_Home - * - * Home key: move to beginning of line. - */ -static void EDIT_Home(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - es->CurrCol = es->WndCol = 0; - if (es->wleft != 0) - { - es->wleft = 0; - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); - } -} - -/********************************************************************* - * EDIT_StickEnd - * - * Stick the cursor to the end of the line. - */ -static void EDIT_StickEnd(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - int len = EDIT_LineLength(hwnd, es->CurrLine); - char *cp = EDIT_TextLine(hwnd, es->CurrLine); - int currpel; - - es->CurrCol = MIN(len, es->CurrCol); - es->WndCol = MIN(EDIT_StrWidth(hwnd, cp, len, 0) - es->wleft, es->WndCol); - currpel = EDIT_StrWidth(hwnd, cp, es->CurrCol, 0); - - if (es->wleft > currpel) - { - es->wleft = MAX(0, currpel - 20); - es->WndCol = currpel - es->wleft; - UpdateWindow(hwnd); - } - else if (currpel - es->wleft >= es->ClientWidth) - { - es->wleft = currpel - (es->ClientWidth - 5); - es->WndCol = currpel - es->wleft; - UpdateWindow(hwnd); - } -} - -/********************************************************************* - * EDIT_Downward - * - * Cursor down key: move down one line. - */ -static void EDIT_Downward(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", - es->WndRow, es->wtop, es->wlines); - - if (IsMultiLine(hwnd) && (es->WndRow + es->wtop + 1 < es->wlines)) - { - es->CurrLine++; - if (es->WndRow == es->ClientHeight - 1) - { - es->WndRow++; - EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN); - } - else - es->WndRow++; - EDIT_StickEnd(hwnd); - } -} - -/********************************************************************* - * EDIT_Upward - * - * Cursor up key: move up one line. - */ -static void EDIT_Upward(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (IsMultiLine(hwnd) && es->CurrLine != 0) - { - --es->CurrLine; - if (es->WndRow == 0) - { - --es->WndRow; - EDIT_KeyVScrollLine(hwnd, SB_LINEUP); - } - else - --es->WndRow; - EDIT_StickEnd(hwnd); - } -} - -/********************************************************************* - * EDIT_Forward - * - * Cursor right key: move right one character position. - */ -static void EDIT_Forward(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (*CurrChar == '\0') - return; - - if (*CurrChar == '\r') - { - if (es->CurrLine < (es->wlines - 1)) - { - EDIT_Home(hwnd); - EDIT_Downward(hwnd); - } - } - else - { - es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft); - es->CurrCol++; - if (es->WndCol >= es->ClientWidth) - EDIT_KeyHScroll(hwnd, SB_LINEDOWN); - } -} - -/********************************************************************* - * EDIT_Backward - * - * Cursor left key: move left one character position. - */ -static void EDIT_Backward(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (es->CurrCol) - { - --es->CurrCol; - if (*CurrChar == VK_TAB) - es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), - EDIT_StrWidth(hwnd, - EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol, 0)); - else - es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0); - if (es->WndCol < 0) - EDIT_KeyHScroll(hwnd, SB_LINEUP); - } - else if (IsMultiLine(hwnd) && es->CurrLine != 0) - { - EDIT_Upward(hwnd); - EDIT_End(hwnd); - } -} - -/********************************************************************* - * EDIT_KeyVScrollPage - * - * Scroll text vertically by one page using keyboard. - */ -static void EDIT_KeyVScrollPage(HWND hwnd, WORD opt) -{ - int vscrollpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (IsMultiLine(hwnd)) - { - if (opt == SB_PAGEUP) - { - if (es->wtop > es->ClientHeight) es->wtop -= es->ClientHeight; - } - else - { - if (es->wtop + es->ClientHeight < es->wlines) - { - es->wtop += es->ClientHeight; - if (es->wtop > es->wlines - es->ClientHeight) - es->wtop = es->wlines - es->ClientHeight; - } - } - if (es->wtop < 0) - es->wtop = 0; - - es->CurrLine = es->wtop + es->WndRow; - EDIT_StickEnd(hwnd); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - - /* reset the vertical scroll bar */ - if (IsVScrollBar(hwnd)) - { - vscrollpos = EDIT_ComputeVScrollPos(hwnd); - SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE); - } - } -} - -#ifdef SUPERFLUOUS_FUNCTIONS -/********************************************************************* - * EDIT_KeyVScrollDoc - * - * Scroll text to top and bottom of document using keyboard. - */ -static void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt) -{ - int vscrollpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (!IsMultiLine(hwnd)) - return; - - if (opt == SB_TOP) - es->wtop = es->wleft = 0; - else if (es->wtop + es->ClientHeight < es->wlines) - { - es->wtop = es->wlines - es->ClientHeight; - es->wleft = 0; - } - - es->CurrLine = es->wlines; - es->WndRow = es->wlines - es->wtop; - EDIT_End(hwnd); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - - /* reset the vertical scroll bar */ - if (IsVScrollBar(hwnd)) - { - vscrollpos = EDIT_ComputeVScrollPos(hwnd); - SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE); - } -} -#endif - -/********************************************************************* - * EDIT_DelKey - * - * Delete character to right of cursor. - */ -static void EDIT_DelKey(HWND hwnd) -{ - RECT rc; - EDITSTATE *es = EDIT_GetEditState(hwnd); - char *currchar = CurrChar; - BOOL repaint; - - if (IsMultiLine(hwnd) && !strncmp(currchar,"\r\n\0",3)) - return; - - if(*currchar == '\n') { - repaint = TRUE; - strcpy(currchar, currchar + 1); - } else if (*currchar == '\r') { - repaint = TRUE; - strcpy(currchar, currchar + 2); - } else { - repaint = FALSE; - strcpy(currchar, currchar + 1); - } - NOTIFY_PARENT(hwnd, EN_UPDATE); - - if (repaint) - { - EDIT_BuildTextPointers(hwnd); - GetClientRect(hwnd, &rc); - rc.top = es->WndRow * es->txtht; - InvalidateRect(hwnd, &rc, FALSE); - UpdateWindow(hwnd); - } - else - { - EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1); - EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop); - } - - es->TextChanged = TRUE; - NOTIFY_PARENT(hwnd, EN_CHANGE); -} - -/********************************************************************* - * EDIT_VScrollLine - * - * Scroll text vertically by one line using scrollbars. - */ -static void EDIT_VScrollLine(HWND hwnd, WORD opt) -{ - RECT rc; - int y; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt); - - if (opt == SB_LINEDOWN) - { - /* move down one line */ - if (es->wtop + es->ClientHeight >= es->wlines) - return; - es->wtop++; - } - else - { - /* move up one line */ - if (es->wtop == 0) - return; - --es->wtop; - } - - if (IsWindowVisible(hwnd)) - { - EDIT_CaretHide(hwnd); - - /* adjust client bottom to nearest whole line */ - GetClientRect(hwnd, &rc); - rc.bottom = (rc.bottom / es->txtht) * es->txtht; - - if (opt == SB_LINEUP) - { - /* move up one line (scroll window down) */ - ScrollWindow(hwnd, 0, es->txtht, &rc, &rc); - /* write top line */ - EDIT_WriteTextLine(hwnd, NULL, es->wtop); - es->WndRow++; - } - else - { - /* move down one line (scroll window up) */ - ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc); - /* write bottom line */ - y = ((rc.bottom - rc.top / es->txtht) - 1); - EDIT_WriteTextLine(hwnd, NULL, es->wtop + y); - --es->WndRow; - } - } -} - - -/********************************************************************* - * EDIT_VScrollPage - * - * Scroll text vertically by one page using keyboard. - */ -static void EDIT_VScrollPage(HWND hwnd, WORD opt) -{ - int vscrollpos; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (opt == SB_PAGEUP) - { - if (es->wtop) - es->wtop -= es->ClientHeight; - } - else - { - if (es->wtop + es->ClientHeight < es->wlines) - { - es->wtop += es->ClientHeight; - if (es->wtop > es->wlines - es->ClientHeight) - es->wtop = es->wlines - es->ClientHeight; - } - } - if (es->wtop < 0) - es->wtop = 0; - - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - - /* reset the vertical scroll bar */ - if (IsVScrollBar(hwnd)) - { - vscrollpos = EDIT_ComputeVScrollPos(hwnd); - SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE); - } -} - -/********************************************************************* - * EDIT_PixelToChar - * - * Convert a pixel offset in the given row to a character offset, - * adjusting the pixel offset to the nearest whole character if - * necessary. - */ -static int EDIT_PixelToChar(HWND hwnd, int row, int *pixel) -{ - int ch = 0, i = 0, s_i = 0; - char *text; - - dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel); - - text = EDIT_TextLine(hwnd, row); - while (i < *pixel) - { - s_i = i; - i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i); - ch++; - } - - /* if stepped past _pixel_, go back a character */ - if (i - *pixel) - { - i = s_i; - --ch; - } - *pixel = i; - return ch; -} - -/********************************************************************* - * EDIT_ClearText - * - * Clear text from text buffer. - */ -static void EDIT_ClearText(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - unsigned int blen = EditBufStartLen(hwnd) + 2; - char *text; - - dprintf_edit(stddeb,"EDIT_ClearText %d\n",blen); - es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen); - text = EDIT_HeapLock(hwnd, es->hText); - memset(text, 0, blen); - es->textlen = 0; - es->wlines = 0; - es->CurrLine = es->CurrCol = 0; - es->WndRow = es->WndCol = 0; - es->wleft = es->wtop = 0; - es->textwidth = 0; - es->TextChanged = FALSE; - EDIT_ClearTextPointers(hwnd); -} - -/********************************************************************* - * EDIT_GetLineCol - * - * Return line and column in text buffer from character offset. - */ -static void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col) -{ - int lineno; - char *cp, *cp1; - EDITSTATE *es = EDIT_GetEditState(hwnd); - char *text = EDIT_HeapLock(hwnd, es->hText); - - /* check for (0,0) */ - if (!off || !es->wlines) - { - *line = 0; - *col = 0; - return; - } - - if (off < 0 || off > strlen(text)) off = strlen(text); - cp1 = text; - for (lineno = 0; lineno < es->wlines; lineno++) - { - cp = text + es->textptrs[lineno]; - if (off == (int)(cp - text)) - { - *line = lineno; - *col = 0; - return; - } - if (off < (int)(cp - text)) - break; - cp1 = cp; - } - *line = lineno - 1; - *col = off - (int)(cp1 - text); -#if 0 - if (*(text + *col) == '\0') - (*col)--; -#endif -} - -/********************************************************************* - * EDIT_UpdateSel - * - * Redraw the current selection, after losing focus, for example. - */ -static void EDIT_UpdateSel(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - int y, bbl, bel; - RECT rc; - - /* Note which lines need redrawing. */ - bbl=MIN(es->SelBegLine,es->SelEndLine); - bel=MAX(es->SelBegLine,es->SelEndLine); - - /* Redraw the affected lines */ - GetClientRect(hwnd, &rc); - for (y = bbl; y <= bel; y++) - { - EDIT_WriteTextLine(hwnd, &rc, y); - } -} - -/********************************************************************* - * EDIT_ClearSel - * - * Clear the current selection. - */ -static void EDIT_ClearSel(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - int y, bbl, bel; - RECT rc; - - /* Note which lines need redrawing. */ - bbl=MIN(es->SelBegLine,es->SelEndLine); - bel=MAX(es->SelBegLine,es->SelEndLine); - - /* Clear the selection */ - es->SelBegLine = es->SelBegCol = 0; - es->SelEndLine = es->SelEndCol = 0; - - /* Redraw the affected lines */ - GetClientRect(hwnd, &rc); - for (y = bbl; y <= bel; y++) - { - EDIT_WriteTextLine(hwnd, &rc, y); - } -} - -/********************************************************************* - * EDIT_SaveDeletedText - * - * Save deleted text in deleted text buffer. - */ -static void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, - int line, int col) -{ - char *text; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - dprintf_edit( stddeb, "EDIT_SaveDeletedText\n" ); - if (!es->hDeletedText) - es->hDeletedText = GlobalAlloc( GMEM_MOVEABLE, len ); - else - es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE); - if (!es->hDeletedText) return; - text = (char *)GlobalLock(es->hDeletedText); - memcpy(text, deltext, len); - GlobalUnlock(es->hDeletedText); - es->DeletedLength = len; - es->DeletedCurrLine = line; - es->DeletedCurrCol = col; -} - -/********************************************************************* - * EDIT_DeleteSel - * - * Delete the current selected text (if any) - */ -static void EDIT_DeleteSel(HWND hwnd) -{ - char *selStart, *selEnd; - int bl, el, bc, ec; - int len; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (SelMarked(es)) - { - /* Get the real beginning and ending lines and columns */ - bl = es->SelBegLine; - el = es->SelEndLine; - if ( bl > el ) { - bl = el; - el = es->SelBegLine; - bc = es->SelEndCol; - ec = es->SelBegCol; - } else if ( bl == el ) { - bc = MIN(es->SelBegCol,es->SelEndCol); - ec = MAX(es->SelBegCol,es->SelEndCol); - } else { - bc = es->SelBegCol; - ec = es->SelEndCol; - } - - selStart = EDIT_TextLine(hwnd, bl) + bc; - selEnd = EDIT_TextLine(hwnd, el) + ec; - len = (int)(selEnd - selStart); - EDIT_SaveDeletedText(hwnd, selStart, len, bl, bc); - es->TextChanged = TRUE; - EDIT_ClearSel(hwnd); - strcpy(selStart, selEnd); - - es->CurrLine = bl; - es->CurrCol = bc; - es->WndRow = bl - es->wtop; - if (es->WndRow < 0) - { - es->wtop = bl; - es->WndRow = 0; - } - es->WndCol = EDIT_StrWidth(hwnd, selStart - bc, bc, 0) - es->wleft; - - EDIT_BuildTextPointers(hwnd); - es->PaintBkgd = TRUE; - - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - } -} - -#ifdef SUPERFLUOUS_FUNCTIONS -/********************************************************************* - * EDIT_TextLineNumber - * - * Return the line number in the text buffer of the supplied - * character pointer. - */ -static int EDIT_TextLineNumber(HWND hwnd, char *lp) -{ - int lineno; - char *cp; - EDITSTATE *es = EDIT_GetEditState(hwnd); - char *text = EDIT_HeapLock(hwnd, es->hText); - - for (lineno = 0; lineno < es->wlines; lineno++) - { - cp = text + es->textptrs[lineno]; - if (cp == lp) - return lineno; - if (cp > lp) - break; - } - return lineno - 1; -} -#endif - -/********************************************************************* - * EDIT_SetAnchor - * - * Set down anchor for text marking. - */ -static void EDIT_SetAnchor(HWND hwnd, int row, int col) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (SelMarked(es)) EDIT_ClearSel(hwnd); - es->SelBegLine = es->SelEndLine = row; - es->SelBegCol = es->SelEndCol = col; -} - -/********************************************************************* - * EDIT_ExtendSel - * - * Extend selection to the given screen co-ordinates. - */ -static void EDIT_ExtendSel(HWND hwnd, INT x, INT y) -{ - int bbl, bel, bbc; - char *cp; - int len, line; - EDITSTATE *es = EDIT_GetEditState(hwnd); - RECT rc; - - dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y); - - bbl = es->SelEndLine; - bbc = es->SelEndCol; - y = MAX(y,0); - if (IsMultiLine(hwnd)) - { - if ((line = es->wtop + y / es->txtht) >= es->wlines) - line = es->wlines - 1; - } - else - line = 0; - - cp = EDIT_TextLine(hwnd, line); - len = EDIT_LineLength(hwnd, line); - - es->WndRow = y / es->txtht; - if (!IsMultiLine(hwnd)) - es->WndRow = 0; - else if (es->WndRow > es->wlines - es->wtop - 1) - es->WndRow = es->wlines - es->wtop - 1; - es->CurrLine = es->wtop + es->WndRow; - es->SelEndLine = es->CurrLine; - - es->WndCol = es->wleft + MAX(x,0); - if (es->WndCol > EDIT_StrWidth(hwnd, cp, len, 0)) - es->WndCol = EDIT_StrWidth(hwnd, cp, len, 0); - es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol)); - es->WndCol -= es->wleft; - es->SelEndCol = es->CurrCol; - - bel = es->SelEndLine; - - /* return if no new characters to mark */ - if (bbl == bel && bbc == es->SelEndCol) return; - - /* put lowest marker first */ - if (bbl > bel) SWAP_INT(bbl, bel); - - /* Update lines on which selection has changed */ - GetClientRect(hwnd, &rc); - for (y = bbl; y <= bel; y++) - { - EDIT_WriteTextLine(hwnd, &rc, y); - } -} - -/********************************************************************* - * EDIT_InsertText - * - * Insert text at current line and column. - */ -static void EDIT_InsertText(HWND hwnd, char *str, int len) -{ - int plen; - EDITSTATE *es = EDIT_GetEditState(hwnd); - char *p, *text = EDIT_HeapLock(hwnd, es->hText); - - plen = strlen(text) + len; - if (plen + 1 > es->textlen) - { - dprintf_edit(stddeb,"InsertText: Realloc\n"); - es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len); - text = EDIT_HeapLock(hwnd, es->hText); - es->textlen = plen + 1; - } - for (p = CurrChar + strlen(CurrChar); p >= CurrChar; p--) p[len] = *p; - memcpy(CurrChar, str, len); - - EDIT_BuildTextPointers(hwnd); - es->PaintBkgd = TRUE; - es->TextChanged = TRUE; - - EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine), - &(es->CurrCol)); - es->WndRow = es->CurrLine - es->wtop; - es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol, 0) - es->wleft; -} - -/********************************************************************* - * EDIT_ClearDeletedText - * - * Clear deleted text buffer. - */ -static void EDIT_ClearDeletedText(HWND hwnd) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - GlobalFree(es->hDeletedText); - es->hDeletedText = 0; - es->DeletedLength = 0; -} - -/********************************************************************* - * EDIT_CopyToClipboard - * - * Copy the specified text to the clipboard. - */ -static void EDIT_CopyToClipboard(HWND hwnd) -{ - HANDLE hMem; - char *lpMem; - int i, len; - char *bbl, *bel; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol; - bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol; - len = (int)(bel - bbl); - - hMem = GlobalAlloc(GHND, (DWORD)(len + 1)); - lpMem = GlobalLock(hMem); - - for (i = 0; i < len; i++) - *lpMem++ = *bbl++; - - GlobalUnlock(hMem); - OpenClipboard(hwnd); - EmptyClipboard(); - SetClipboardData(CF_TEXT, hMem); - CloseClipboard(); -} - -/********************************************************************* - * EDIT_KeyTyped - * - * Process keystrokes that produce displayable characters. - */ -static void EDIT_KeyTyped(HWND hwnd, short ch) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - char *text = EDIT_HeapLock(hwnd, es->hText); - char *currchar, *p; - RECT rc; - BOOL FullPaint = FALSE; - - dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch); - - /* delete selected text (if any) */ - if (SelMarked(es)) - EDIT_DeleteSel(hwnd); - - /* currchar must be assigned after deleting the selection */ - currchar = CurrChar; - - /* test for typing at end of maximum buffer size */ - if (currchar == text + es->MaxTextLen) - { - NOTIFY_PARENT(hwnd, EN_ERRSPACE); - return; - } - - if (*currchar == '\0' && IsMultiLine(hwnd)) - { - /* insert a newline at end of text */ - *currchar = '\r'; - *(currchar + 1) = '\n'; - *(currchar + 2) = '\0'; - EDIT_BuildTextPointers(hwnd); - } - - /* insert the typed character */ - if (text[es->textlen - 1] != '\0') - { - /* current text buffer is full */ - if (es->textlen == es->MaxTextLen) - { - /* text buffer is at maximum size */ - NOTIFY_PARENT(hwnd, EN_ERRSPACE); - return; - } - - /* increase the text buffer size */ - es->textlen += GROWLENGTH; - /* but not above maximum size */ - if (es->textlen > es->MaxTextLen) - es->textlen = es->MaxTextLen; - dprintf_edit( stddeb, "EDIT_KeyTyped: realloc\n" ); - es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2); - if (!es->hText) - NOTIFY_PARENT(hwnd, EN_ERRSPACE); - text = EDIT_HeapLock(hwnd, es->hText); - text[es->textlen - 1] = '\0'; - currchar = CurrChar; - } - /* make space for new character and put char in buffer */ - if (ch == '\n') - { - for (p = currchar + strlen(currchar); p >= currchar; p--) p[2] = p[0]; - *currchar = '\r'; - *(currchar + 1) = '\n'; - EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2); - } - else - { - for (p = currchar + strlen(currchar); p >= currchar; p--) p[1] = p[0]; - *currchar = ch; - EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1); - } - es->TextChanged = TRUE; - NOTIFY_PARENT(hwnd, EN_UPDATE); - - /* re-adjust textwidth, if necessary, and redraw line */ - if (IsMultiLine(hwnd) && es->wlines > 1) - { - es->textwidth = MAX(es->textwidth, - EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine), - (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) - - EDIT_TextLine(hwnd, es->CurrLine)), 0)); - } else { - es->textwidth = MAX(es->textwidth, - EDIT_StrWidth(hwnd, text, strlen(text), 0)); - } - - if (ch == '\n') - { - if (es->wleft > 0) - FullPaint = TRUE; - es->wleft = 0; - EDIT_BuildTextPointers(hwnd); - EDIT_End(hwnd); - EDIT_Forward(hwnd); - EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol); - - /* invalidate rest of window */ - GetClientRect(hwnd, &rc); - if (!FullPaint) - rc.top = es->WndRow * es->txtht; - InvalidateRect(hwnd, &rc, FALSE); - - UpdateWindow(hwnd); - NOTIFY_PARENT(hwnd, EN_CHANGE); - return; - } - - /* test end of window */ - if (es->WndCol >= es->ClientWidth - - EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft)) - { - /* TODO:- Word wrap to be handled here */ - -/* if (!(currchar == text + es->MaxTextLen - 2)) */ - EDIT_KeyHScroll(hwnd, SB_LINEDOWN); - } - es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft); - es->CurrCol++; - EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol); - EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow); - NOTIFY_PARENT(hwnd, EN_CHANGE); - dprintf_edit(stddeb,"KeyTyped O.K.\n"); -} - -/********************************************************************* - * EM_UNDO message function - */ -static LRESULT EDIT_UndoMsg(HWND hwnd) -{ - char *text; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (es->hDeletedText) - { - text = (char *)GlobalLock(es->hDeletedText); - es->CurrLine = es->DeletedCurrLine; - es->CurrCol = es->DeletedCurrCol; - EDIT_InsertText(hwnd, text, es->DeletedLength); - GlobalUnlock(es->hDeletedText); - EDIT_ClearDeletedText(hwnd); - - es->SelBegLine = es->CurrLine; - es->SelBegCol = es->CurrCol; - EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text), - &(es->CurrLine), &(es->CurrCol)); - es->WndRow = es->CurrLine - es->wtop; - es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol, 0) - es->wleft; - es->SelEndLine = es->CurrLine; - es->SelEndCol = es->CurrCol; - - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - return 1; - } - else - return 0; -} - -/********************************************************************* - * EM_SETHANDLE message function - */ -static void EDIT_SetHandleMsg(HWND hwnd, WPARAM wParam) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (IsMultiLine(hwnd)) - { - es->hText = (HANDLE)wParam; - es->textlen = EDIT_HeapSize(hwnd, es->hText); - es->wlines = 0; - es->wtop = es->wleft = 0; - es->CurrLine = es->CurrCol = 0; - es->WndRow = es->WndCol = 0; - es->TextChanged = FALSE; - es->textwidth = 0; - es->SelBegLine = es->SelBegCol = 0; - es->SelEndLine = es->SelEndCol = 0; - dprintf_edit(stddeb, "EDIT_SetHandleMsg: handle %04x, textlen=%d\n", - wParam, es->textlen); - - EDIT_BuildTextPointers(hwnd); - es->PaintBkgd = TRUE; - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - } -} - -/********************************************************************* - * EM_SETTABSTOPS message function - */ -static LRESULT EDIT_SetTabStopsMsg(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - dprintf_edit( stddeb, "EDIT_SetTabStops\n" ); - es->NumTabStops = wParam; - if (wParam == 0) - es->TabStops = xrealloc(es->TabStops, 2); - else if (wParam == 1) - { - es->TabStops = xrealloc(es->TabStops, 2); - es->TabStops[0] = LOWORD(lParam); - } - else - { - es->TabStops = xrealloc(es->TabStops, wParam * sizeof(*es->TabStops)); - memcpy(es->TabStops, (unsigned short *)PTR_SEG_TO_LIN(lParam), wParam); - } - return 0; -} - -/********************************************************************* - * EM_GETLINE message function - */ -static LRESULT EDIT_GetLineMsg(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - char *cp; - int len = 0; - unsigned char *buffer = (char *)PTR_SEG_TO_LIN(lParam); - - /* the line wanted */ - cp = EDIT_TextLine (hwnd, wParam); - len = EDIT_LineLength(hwnd, wParam); - - /* if cp==NULL nothing will be copied - I hope */ - if ((char *) NULL == cp && 0 != len) { - fprintf(stdnimp,"edit: EDIT_GetLineMsg cp == NULL && len != 0"); - return 0L; - } - - if (0>len) - fprintf(stdnimp,"edit: EDIT_GetLineMsg len < 0"); - - /* suggested reason for the following line: - never copy more than the buffer's size ? - I thought that this would make sense only if - the lstrcpyn fun was used instead of the gnu strncpy. - */ - len = MIN(len, (WORD)(*buffer)); - - if (0>len) - fprintf(stdnimp,"edit: EDIT_GetLineMsg len < 0 after MIN"); - - dprintf_edit( stddeb, "EDIT_GetLineMsg: %d %d, len %d\n", (int)(WORD)(*buffer), (int)(WORD)(*(char *)buffer), len); - lstrcpyn(buffer, cp, len); - - return (LRESULT)len; -} - -/********************************************************************* - * EM_GETSEL message function - */ -static LRESULT EDIT_GetSelMsg(HWND hwnd) -{ - int so, eo; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - so = es->textptrs[es->SelBegLine] + es->SelBegCol; - eo = es->textptrs[es->SelEndLine] + es->SelEndCol; - - return (LRESULT)MAKELONG(so, eo); -} - -/********************************************************************* - * EM_REPLACESEL message function - */ -static void EDIT_ReplaceSel(HWND hwnd, LPARAM lParam) -{ - EDIT_DeleteSel(hwnd); - EDIT_InsertText(hwnd, (char *)PTR_SEG_TO_LIN(lParam), - strlen((char *)PTR_SEG_TO_LIN(lParam))); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); -} - -/********************************************************************* - * EM_LINEFROMCHAR message function - */ -static LRESULT EDIT_LineFromCharMsg(HWND hwnd, WPARAM wParam) -{ - int row, col; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (wParam == (WORD)-1) - return (LRESULT)(es->SelBegLine); - else - EDIT_GetLineCol(hwnd, wParam, &row, &col); - - return (LRESULT)row; -} - - -/********************************************************************* - * EM_LINEINDEX message function - */ -static LRESULT EDIT_LineIndexMsg(HWND hwnd, WPARAM wParam) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (wParam == (WORD)-1) wParam = es->CurrLine; - return es->textptrs[wParam]; -} - - -/********************************************************************* - * EM_LINELENGTH message function - */ -static LRESULT EDIT_LineLengthMsg(HWND hwnd, WPARAM wParam) -{ - int row, col, len; - int sbl, sbc, sel, sec; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - if (wParam == (WORD)-1) - { - if (SelMarked(es)) - { - sbl = es->SelBegLine; - sbc = es->SelBegCol; - sel = es->SelEndLine; - sec = es->SelEndCol; - - if (sbl > sel) - { - SWAP_INT(sbl, sel); - SWAP_INT(sbc, sec); - } - if (sbl == sel && sbc > sec) - SWAP_INT(sbc, sec); - - if (sbc == sel) - { - len = es->textptrs[sbl + 1] - es->textptrs[sbl] - 1; - return len - sec - sbc; - } - - len = es->textptrs[sel + 1] - es->textptrs[sel] - sec - 1; - return len + sbc; - } - else /* no selection marked */ - { - len = es->textptrs[es->CurrLine + 1] - es->textptrs[es->CurrLine] - 1; - return len; - } - } - else /* line number specified */ - { - EDIT_GetLineCol(hwnd, wParam, &row, &col); - len = es->textptrs[row + 1] - es->textptrs[row]; - return len; - } -} - -/********************************************************************* - * EM_SETSEL message function - */ -static void EDIT_SetSelMsg(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - INT so, eo; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - so = LOWORD(lParam); - eo = HIWORD(lParam); - - if (so == -1) /* if so == -1, clear selection */ - { - EDIT_ClearSel(hwnd); - return; - } - - if (so == eo) /* if so == eo, set caret only */ - { - EDIT_GetLineCol(hwnd, (int) so, &(es->CurrLine), &(es->CurrCol)); - es->WndRow = es->CurrLine - es->wtop; - - if (!wParam) - { - if (es->WndRow < 0 || es->WndRow > es->ClientHeight) - { - es->wtop = es->CurrLine; - es->WndRow = 0; - } - es->WndCol = EDIT_StrWidth(hwnd, - EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol, 0) - es->wleft; - if (es->WndCol > es->ClientWidth) - { - es->wleft = es->WndCol; - es->WndCol = 0; - } - else if (es->WndCol < 0) - { - es->wleft += es->WndCol; - es->WndCol = 0; - } - } - } - else /* otherwise set selection */ - { - if (eo >= 0 && so > eo) /* eo == -1 flag to extend to end of text */ - { - INT tmp; - tmp = so; - so = eo; - eo = tmp; - } - - EDIT_GetLineCol(hwnd, (int) so, &(es->SelBegLine), &(es->SelBegCol)); - EDIT_GetLineCol(hwnd, (int) eo, &(es->SelEndLine), &(es->SelEndCol)); - es->CurrLine = es->SelEndLine; - es->CurrCol = es->SelEndCol; - es->WndRow = es->SelEndLine - es->wtop; - - if (!wParam) /* don't suppress scrolling of text */ - { - if (es->WndRow < 0) - { - es->wtop = es->SelEndLine; - es->WndRow = 0; - } - else if (es->WndRow > es->ClientHeight) - { - es->wtop += es->WndRow - es->ClientHeight; - es->WndRow = es->ClientHeight; - } - es->WndCol = EDIT_StrWidth(hwnd, - EDIT_TextLine(hwnd, es->SelEndLine), - es->SelEndCol, 0) - es->wleft; - if (es->WndCol > es->ClientWidth) - { - es->wleft += es->WndCol - es->ClientWidth; - es->WndCol = es->ClientWidth; - } - else if (es->WndCol < 0) - { - es->wleft += es->WndCol; - es->WndCol = 0; - } - } - - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - } -} - -/********************************************************************* - * WM_SETFONT - */ -static void EDIT_WM_SetFont(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HDC hdc; - TEXTMETRIC tm; - HFONT oldfont; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - es->hFont = (HANDLE)wParam; - hdc = GetDC(hwnd); - oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont); - GetCharWidth(hdc, 0, 255, es->CharWidths); - GetTextMetrics(hdc, &tm); - es->txtht = tm.tmHeight + tm.tmExternalLeading; - SelectObject(hdc, (HANDLE)oldfont); - ReleaseDC(hwnd, hdc); - - es->WndRow = (es->CurrLine - es->wtop) / es->txtht; - es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol, 0) - es->wleft; - - InvalidateRect(hwnd, NULL, TRUE); - es->PaintBkgd = TRUE; - if (lParam) UpdateWindow(hwnd); - EDIT_RecalcSize(hwnd,es); - - if (es->HaveFocus) - { - EDIT_CaretHide(hwnd); - DestroyCaret(); - CreateCaret(hwnd, 0, 2, es->txtht); - SetCaretPos(es->WndCol, es->WndRow * es->txtht); - } -} - -/********************************************************************* - * WM_PASTE - */ -static void EDIT_WM_Paste(HWND hwnd) -{ - HANDLE hClipMem; - char *lpClipMem; - - OpenClipboard(hwnd); - if (!(hClipMem = GetClipboardData(CF_TEXT))) - { - /* no text in clipboard */ - CloseClipboard(); - return; - } - lpClipMem = GlobalLock(hClipMem); - EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem)); - GlobalUnlock(hClipMem); - CloseClipboard(); - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); -} - -/********************************************************************* - * WM_PAINT - */ -static void EDIT_WM_Paint(HWND hwnd) -{ - PAINTSTRUCT ps; - HDC hdc; - int y; - RECT rc; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - EDIT_CaretHide(hwnd); - - hdc = BeginPaint(hwnd, &ps); - GetClientRect(hwnd, &rc); - IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); - - dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n", - rc.left, rc.top, rc.right, rc.bottom); - - if (es->PaintBkgd) - FillWindow(GetParent(hwnd), hwnd, hdc, (HBRUSH)CTLCOLOR_EDIT); - - for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++) - { - if (y < (IsMultiLine(hwnd) ? es->wlines : 1) - es->wtop) - EDIT_WriteTextLine(hwnd, &rc, y + es->wtop); - } - - EndPaint(hwnd, &ps); -} - -static BOOL LOCAL_HeapExists(HANDLE ds) -{ -/* There is always a local heap in WineLib */ -#ifndef WINELIB - INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( ds, 0 ); - if (!ptr->heap) return 0; -#endif - return 1; -} - -/********************************************************************* - * WM_NCCREATE - */ -static long EDIT_WM_NCCreate(HWND hwnd, LPARAM lParam) -{ - CREATESTRUCT *createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam); - WND *wndPtr = WIN_FindWndPtr(hwnd); - EDITSTATE *es; - char *text = NULL; - HANDLE ds; - - /* store pointer to local or global heap in window structure so that */ - /* EDITSTATE structure itself can be stored on local heap */ - /* allocate space for state variable structure */ - es = xmalloc( sizeof(EDITSTATE) ); - SetWindowLong( hwnd, 0, (LONG)es ); - es->textptrs = xmalloc(sizeof(int)); - es->CharWidths = xmalloc(256 * sizeof(INT)); - es->ClientWidth = es->ClientHeight = 1; - /* --- text buffer */ - es->MaxTextLen = MAXTEXTLEN + 1; - es->PasswordChar = '*'; - - es->WordBreakProc = NULL; - - /* Caret stuff */ - es->CaretPrepareCount = 1; - es->CaretHidden = 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) - * as the global block - */ - ds = WIN_GetWindowInstance(hwnd); - - if (!LOCAL_HeapExists(ds)) - { - DWORD globalSize; - globalSize = GlobalSize(ds); - dprintf_edit(stddeb, "No local heap allocated global size is %ld 0x%lx\n",globalSize, globalSize); - /* - * I assume the local heap should start at 0 - */ - LocalInit(ds, 0, globalSize); - /* - * Apparantly we should do an UnlockSegment here but i think this - * is because LocalInit is supposed to do a LockSegment. Since - * Local Init doesn't do this then it doesn't seem like a good idea to do the - * UnlockSegment here yet! - * UnlockSegment(hwnd); - */ - - } - - - if (!(createStruct->lpszName)) - { - dprintf_edit( stddeb, "EDIT_WM_NCCREATE: lpszName == 0\n" ); - es->textlen = EditBufStartLen(hwnd) + 1; - es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE); - text = EDIT_HeapLock(hwnd, es->hText); - memset(text, 0, es->textlen + 2); - es->wlines = 0; - es->textwidth = 0; - EDIT_ClearTextPointers(hwnd); - if (IsMultiLine(hwnd)) strcpy(text, "\r\n"); - EDIT_BuildTextPointers(hwnd); - } - else - { - char *windowName = (char *)PTR_SEG_TO_LIN( createStruct->lpszName ); - dprintf_edit( stddeb, "EDIT_WM_NCCREATE: lpszName != 0\n" ); - - if (strlen(windowName) < EditBufStartLen(hwnd)) - { - es->textlen = EditBufStartLen(hwnd) + 3; - es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE); - if (es->hText) - { - text = EDIT_HeapLock(hwnd, es->hText); - if (text) - { - strcpy(text, windowName); - if(IsMultiLine(hwnd)) { - strcat(text, "\r\n"); - } - *(text + es->textlen) = '\0'; - } - } - } - else - { - es->textlen = strlen(windowName) + 3; - es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE); - text = EDIT_HeapLock(hwnd, es->hText); - strcpy(text, windowName); - if(IsMultiLine(hwnd)) strcat(text, "\r\n"); - *(text + es->textlen) = '\0'; - } - if (text) - { - *(text + es->textlen + 1) = '\0'; - EDIT_BuildTextPointers(hwnd); - } - } - - /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */ - /* the corresponding WS_* style is set */ - if (createStruct->style & WS_VSCROLL) - wndPtr->dwStyle |= ES_AUTOVSCROLL; - if (createStruct->style & WS_HSCROLL) - wndPtr->dwStyle |= ES_AUTOHSCROLL; - - /* remove the WS_CAPTION style if it has been set - this is really a */ - /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */ - if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME) - wndPtr->dwStyle ^= WS_DLGFRAME; - - return 1; -} - -/********************************************************************* - * WM_CREATE - */ -static LRESULT EDIT_WM_Create(HWND hwnd, LPARAM lParam) -{ - HDC hdc; - EDITSTATE *es = EDIT_GetEditState(hwnd); - CLASS *classPtr; - TEXTMETRIC tm; - - /* initialize state variable structure */ - hdc = GetDC(hwnd); - - /* --- char width array */ - /* only initialise chars <= 32 as X returns strange widths */ - /* for other chars */ - memset(es->CharWidths, 0, 256 * sizeof(INT)); - GetCharWidth(hdc, 32, 254, &es->CharWidths[32]); - - /* --- other structure variables */ - GetTextMetrics(hdc, &tm); - es->txtht = tm.tmHeight + tm.tmExternalLeading; - EDIT_RecalcSize(hwnd,es); - es->wtop = es->wleft = 0; - es->CurrCol = es->CurrLine = 0; - es->WndCol = es->WndRow = 0; - es->TextChanged = FALSE; - es->SelBegLine = es->SelBegCol = 0; - es->SelEndLine = es->SelEndCol = 0; - es->hFont = 0; - es->hDeletedText = 0; - es->DeletedLength = 0; - es->NumTabStops = 0; - es->TabStops = xmalloc( sizeof(short) ); - - /* set up text cursor for edit class */ - { - char editname[] = "EDIT"; - CLASS_FindClassByName( MAKE_SEGPTR(editname), 0, &classPtr); - classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM); - } - - /* paint background on first WM_PAINT */ - es->PaintBkgd = TRUE; - - ReleaseDC(hwnd, hdc); - return 0L; -} - -/********************************************************************* - * WM_VSCROLL - */ -static void EDIT_WM_VScroll(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ -/* - * EDITSTATE *es = EDIT_GetEditState(hwnd); - */ - if (IsMultiLine(hwnd)) - { - switch (wParam) - { - case SB_LINEUP: - case SB_LINEDOWN: - EDIT_VScrollLine(hwnd, wParam); - break; - - case SB_PAGEUP: - case SB_PAGEDOWN: - EDIT_VScrollPage(hwnd, wParam); - break; - } - } -} - -/********************************************************************* - * WM_HSCROLL - */ -static void EDIT_WM_HScroll(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ -/* - * EDITSTATE *es = EDIT_GetEditState(hwnd); - */ - switch (wParam) - { - case SB_LINEUP: - case SB_LINEDOWN: - break; - } -} - -/********************************************************************* - * WM_SIZE - */ -static void EDIT_WM_Size(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - - EDIT_RecalcSize(hwnd,es); - if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return; - InvalidateRect(hwnd, NULL, TRUE); - es->PaintBkgd = TRUE; - UpdateWindow(hwnd); -} - -/********************************************************************* - * WM_LBUTTONDOWN - */ -static void EDIT_WM_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - char *cp; - int len; - BOOL end = FALSE; - EDITSTATE *es = EDIT_GetEditState(hwnd); - - ButtonDown = TRUE; - - if ((wParam & MK_SHIFT)) { - EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam)); - return; - } - - es->WndRow = HIWORD(lParam) / es->txtht; - dprintf_edit( stddeb, "EDIT_LButtonDown: %04x %08lx, WndRow %d\n", wParam, - lParam, es->WndRow ); - if (!IsMultiLine(hwnd)) es->WndRow = 0; - else if (es->WndRow > es->wlines - es->wtop - 1) - { - es->WndRow = es->wlines - es->wtop - 1; - end = TRUE; - } - es->CurrLine = es->wtop + es->WndRow; - - cp = EDIT_TextLine(hwnd, es->CurrLine); - len = EDIT_LineLength(hwnd, es->CurrLine); - es->WndCol = LOWORD(lParam) + es->wleft; - if (end || es->WndCol > EDIT_StrWidth(hwnd, cp, len, 0)) - es->WndCol = EDIT_StrWidth(hwnd, cp, len, 0); - dprintf_edit( stddeb, "EDIT_LButtonDown: CurrLine %d wtop %d wndcol %d\n", - es->CurrLine, es->wtop, es->WndCol); - es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol)); - es->WndCol -= es->wleft; - - ButtonRow = es->CurrLine; - ButtonCol = es->CurrCol; - EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol); -} - -/********************************************************************* - * WM_MOUSEMOVE - */ -static void EDIT_WM_MouseMove(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ -/* - * EDITSTATE *es = EDIT_GetEditState(hwnd); - */ - if (!(wParam & MK_LBUTTON)) return; - - if (ButtonDown) - { - TextMarking = TRUE; - ButtonDown = FALSE; - } - - if (TextMarking) - EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam)); -} - -/********************************************************************* - * WM_CHAR - */ -static void EDIT_WM_Char(HWND hwnd, WPARAM wParam) -{ - dprintf_edit(stddeb,"EDIT_WM_Char: wParam=%c\n", (char)wParam); - - switch (wParam) - { - case '\r': - 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; - } -} - -/********************************************************************* - * WM_KEYDOWN - */ -static void EDIT_WM_KeyDown(HWND hwnd, WPARAM wParam) -{ - EDITSTATE *es = EDIT_GetEditState(hwnd); - BOOL motionKey = FALSE; - - dprintf_edit(stddeb,"EDIT_WM_KeyDown: key=%x\n", wParam); - - switch (wParam) - { - case VK_UP: - if (IsMultiLine(hwnd)) - EDIT_Upward(hwnd); - else - EDIT_Backward(hwnd); - motionKey = TRUE; - break; - - case VK_DOWN: - if (IsMultiLine(hwnd)) - EDIT_Downward(hwnd); - else - EDIT_Forward(hwnd); - motionKey = TRUE; - break; - - case VK_RIGHT: - EDIT_Forward(hwnd); - motionKey = TRUE; - break; - - case VK_LEFT: - EDIT_Backward(hwnd); - motionKey = TRUE; - break; - - case VK_HOME: - EDIT_Home(hwnd); - motionKey = TRUE; - break; - - case VK_END: - EDIT_End(hwnd); - motionKey = TRUE; - break; - - case VK_PRIOR: - if (IsMultiLine(hwnd)) - { - EDIT_KeyVScrollPage(hwnd, SB_PAGEUP); - } - motionKey = TRUE; - break; - - case VK_NEXT: - if (IsMultiLine(hwnd)) - { - EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN); - } - motionKey = TRUE; - break; - - case VK_BACK: - if (IsReadOnly(hwnd)) break; - if (SelMarked(es)) - EDIT_DeleteSel(hwnd); - else - { - if (es->CurrCol == 0 && es->CurrLine == 0) + 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: EDIT_WordBreakProc: unknown action code, please report !\n"); break; - EDIT_Backward(hwnd); - EDIT_DelKey(hwnd); } - break; - - case VK_DELETE: - if (IsReadOnly(hwnd)) break; - if (SelMarked(es)) - EDIT_DeleteSel(hwnd); - else - EDIT_DelKey(hwnd); - break; - - case VK_SHIFT: - motionKey = TRUE; - break; - - default: - return; - } - - if(motionKey && (0x8000 & GetKeyState(VK_SHIFT))) { - EDIT_ExtendSel(hwnd, es->WndCol, es->WndRow*es->txtht); - } else { - EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol); - } + return ret; } -/********************************************************************* - * WM_SETTEXT - */ -static LRESULT EDIT_WM_SetText(HWND hwnd, LPARAM lParam) -{ - int len; - char *text,*settext; - EDITSTATE *es = EDIT_GetEditState(hwnd); - settext = PTR_SEG_TO_LIN( lParam ); - dprintf_edit( stddeb,"WM_SetText, length %d\n",strlen(settext) ); - if (strlen(settext) <= es->MaxTextLen) - { - len = settext != NULL ? strlen(settext) : 0; - EDIT_ClearText(hwnd); - es->textlen = len; - dprintf_edit( stddeb, "EDIT_WM_SetText: realloc\n" ); - es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3); - text = EDIT_HeapLock(hwnd, es->hText); - if (lParam) - strcpy(text, (char *)PTR_SEG_TO_LIN(lParam)); - text[len] = '\0'; - text[len + 1] = '\0'; - text[len + 2] = '\0'; - EDIT_BuildTextPointers(hwnd); - InvalidateRect(hwnd, NULL, TRUE); - es->PaintBkgd = TRUE; - es->TextChanged = TRUE; - return 0; - } - else - return EN_ERRSPACE; +/********************************************************************* + * + * EM_CANUNDO + * + */ +static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return 0L; } -/********************************************************************* - * 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); +/********************************************************************* + * + * EM_EMPTYUNDOBUFFER + * + */ +static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return 0L; } + /********************************************************************* - * EditWndProc() + * + * EM_FMTLINES + * */ -LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam) { - LRESULT lResult = 0; - char *textPtr; - int len; - EDITSTATE *es = EDIT_GetEditState(hwnd); + fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n"); + return wParam ? -1L : 0L; +} - EDIT_CaretPrepare(hwnd); - switch (uMsg) { - case EM_CANUNDO: - lResult = (LRESULT)es->hDeletedText; - break; +/********************************************************************* + * + * EM_GETFIRSTVISIBLELINE + * + */ +static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); - case EM_EMPTYUNDOBUFFER: - EDIT_ClearDeletedText(hwnd); - break; + return (LRESULT)es->FirstVisibleLine; +} - case EM_FMTLINES: - fprintf(stdnimp,"edit: EM_FMTLINES message received\n"); - if (!wParam) - lResult = 1L; - else - lResult = 0L; - break; - case EM_GETFIRSTVISIBLELINE: - lResult = es->wtop; - break; +/********************************************************************* + * + * EM_GETHANDLE + * + */ +static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); - case EM_GETHANDLE: - lResult = (LRESULT)es->hText; - break; + return (LRESULT)es->hBuf; +} + - case EM_GETLINE: - if (IsMultiLine(hwnd)) - lResult = EDIT_GetLineMsg(hwnd, wParam, lParam); - break; +/********************************************************************* + * + * EM_GETLINE + * + */ +static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + char *text; + char *src; + char *dst; + int len; + int i; + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); - case EM_GETLINECOUNT: - if (IsMultiLine(hwnd)) - lResult = es->wlines; - break; + if (!IsMultiLine(wndPtr)) + wParam = 0; + if ((UINT)wParam >= linecount) + return 0L; + text = EDIT_GetPointer(wndPtr); + src = text + EDIT_EM_LineIndex(wndPtr, wParam, 0L); + dst = (char *)PTR_SEG_TO_LIN(lParam); + len = MIN(*(WORD *)dst, EDIT_EM_LineLength(wndPtr, wParam, 0L)); + for (i = 0 ; i < len ; i++) { + *dst = *src; + src++; + dst++; + } + return (LRESULT)len; +} - case EM_GETMODIFY: - lResult = es->TextChanged; - break; - case EM_GETPASSWORDCHAR: - lResult = es->PasswordChar; - break; +/********************************************************************* + * + * EM_GETLINECOUNT + * + */ +static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return (LRESULT)es->LineCount; +} - case EM_GETRECT: - GetWindowRect(hwnd, (LPRECT)PTR_SEG_TO_LIN(lParam)); - break; - case EM_GETSEL: - lResult = EDIT_GetSelMsg(hwnd); - break; +/********************************************************************* + * + * EM_GETMODIFY + * + */ +static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); - case EM_GETWORDBREAKPROC: - dprintf_edit(stddeb, "EM_GETWORDBREAKPROC\n"); - lResult = (LRESULT)es->WordBreakProc; - break; + return (LRESULT)es->TextChanged; +} - case EM_LIMITTEXT: - if (wParam) - es->MaxTextLen = wParam; - else if (IsMultiLine(hwnd)) - es->MaxTextLen = 65535; - else - es->MaxTextLen = 32767; - break; - case EM_LINEFROMCHAR: - lResult = EDIT_LineFromCharMsg(hwnd, wParam); - break; +/********************************************************************* + * + * EM_GETPASSWORDCHAR + * + */ +static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); - case EM_LINEINDEX: - if (IsMultiLine(hwnd)) - lResult = EDIT_LineIndexMsg(hwnd, wParam); - break; + return (LRESULT)es->PasswordChar; +} - case EM_LINELENGTH: - lResult = EDIT_LineLengthMsg(hwnd, wParam); - break; - case EM_LINESCROLL: - fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n"); - break; +/********************************************************************* + * + * EM_GETRECT + * + */ +static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam)); +} - case EM_REPLACESEL: - EDIT_ReplaceSel(hwnd, lParam); - break; - case EM_SETHANDLE: - EDIT_ClearDeletedText(hwnd); - EDIT_SetHandleMsg(hwnd, wParam); - break; +/********************************************************************* + * + * EM_GETSEL + * + */ +static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return MAKELONG(es->SelStart, es->SelEnd); +} + + +/********************************************************************* + * + * EM_GETTHUMB + * + * undocumented: is this right ? + * + */ +static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), + EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L)); +} + + +/********************************************************************* + * + * EM_GETWORDBREAKPROC + * + */ +static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return (LRESULT)es->WordBreakProc; +} + + +/********************************************************************* + * + * EM_LIMITTEXT + * + */ +static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + if (IsMultiLine(wndPtr)) { + if (wParam) + es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI); + else + es->BufLimit = BUFLIMIT_MULTI; + } else { + if (wParam) + es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE); + else + es->BufLimit = BUFLIMIT_SINGLE; + } + return 0L; +} + + +/********************************************************************* + * + * EM_LINEFROMCHAR + * + */ +static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int l; + + if (!IsMultiLine(wndPtr)) + return 0L; + if ((INT)wParam == -1) + wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + l = EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1; + while (EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam) + l--; + return (LRESULT)l; +} + + +/********************************************************************* + * + * EM_LINEINDEX + * + */ +static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + int e; + int l; + + if ((INT)wParam < 0) { + e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + l = EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1; + while (es->LineDefs[l].offset > (UINT)wParam) + l--; + return (LRESULT)es->LineDefs[l].offset; + } + if (wParam >= es->LineCount) + return -1L; + return (LRESULT)es->LineDefs[wParam].offset; +} + + +/********************************************************************* + * + * EM_LINELENGTH + * + */ +static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + int SelStartLine; + int SelEndLine; + + if (!IsMultiLine(wndPtr)) + return (LRESULT)es->LineDefs[0].length; + if ((INT)wParam >= 0) + return (LRESULT)es->LineDefs[EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length; + SelStartLine = EDIT_EM_LineFromChar(wndPtr, es->SelStart, 0L); + SelEndLine = EDIT_EM_LineFromChar(wndPtr, es->SelEnd, 0L); + return (LRESULT)(es->SelStart - es->LineDefs[SelStartLine].offset + + es->LineDefs[SelEndLine].offset + + es->LineDefs[SelEndLine].length - es->SelEnd); +} + + +/********************************************************************* + * + * EM_LINESCROLL + * + */ +static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + int newfirstvis = firstvis + (INT)LOWORD(lParam); + int xoffset = EDIT_GetXOffset(wndPtr); + int newxoffset = xoffset + (INT)HIWORD(lParam); + int textwidth = EDIT_GetTextWidth(wndPtr); + int dx; + int dy; + POINT pos; + HRGN hRgn; + + if (newfirstvis < 0) + newfirstvis = 0; + if (newfirstvis >= linecount) + newfirstvis = linecount - 1; + + if (newxoffset < 0) + newxoffset = 0; + if (newxoffset >= textwidth) + newxoffset = textwidth; + dx = xoffset - newxoffset; + dy = EDIT_WndYFromLine(wndPtr, firstvis) - EDIT_WndYFromLine(wndPtr, newfirstvis); + if (dx || dy) { + if (wndPtr->hwndSelf == GetFocus()) + HideCaret(wndPtr->hwndSelf); + if (EDIT_GetRedraw(wndPtr)) { + hRgn = CreateRectRgn(0, 0, 0, 0); + GetUpdateRgn(wndPtr->hwndSelf, hRgn, FALSE); + ValidateRgn(wndPtr->hwndSelf, 0); + OffsetRgn(hRgn, dx, dy); + InvalidateRgn(wndPtr->hwndSelf, hRgn, TRUE); + DeleteObject(hRgn); + ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL); + } + es->FirstVisibleLine = newfirstvis; + es->XOffset = newxoffset; + if (IsVScrollBar(wndPtr)) + SetScrollPos(wndPtr->hwndSelf, SB_VERT, + EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE); + if (IsHScrollBar(wndPtr)) + SetScrollPos(wndPtr->hwndSelf, SB_HORZ, + EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE); + if (wndPtr->hwndSelf == GetFocus()) { + GetCaretPos(&pos); + SetCaretPos(pos.x + dx, pos.y + dy); + ShowCaret(wndPtr->hwndSelf); + } + } + return -1L; +} + + +/********************************************************************* + * + * EM_REPLACESEL + * + */ +static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam, + (LPARAM)(char *)PTR_SEG_TO_LIN(lParam)); +} + + +/********************************************************************* + * + * EM_SCROLL + * + * FIXME: undocumented message. + */ +static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n"); + return 0L; +} + + +/********************************************************************* + * + * EM_SETHANDLE + * + */ +static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + if (IsMultiLine(wndPtr)) { + EDIT_ReleasePointer(wndPtr); + /* + * FIXME: specs say: old buffer should be freed + * by the aplication, but e.g. Notepad doesn't. + * Should we LOCAL_Free() the old hBuf ? + */ + LOCAL_Free(wndPtr->hInstance, es->hBuf); + es->hBuf = (HLOCAL)wParam; + es->BufSize = MIN(1, LOCAL_Size(wndPtr->hInstance, es->hBuf)) - 1; + es->hBuf = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, es->BufSize + 1, LMEM_MOVEABLE); + es->LineCount = 0; + es->FirstVisibleLine = 0; + es->SelStart = es->SelEnd = 0; + EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L); + EDIT_EM_SetModify(wndPtr, FALSE, 0L); + EDIT_BuildLineDefs(wndPtr); + if (EDIT_GetRedraw(wndPtr)) + InvalidateRect(wndPtr->hwndSelf, NULL, TRUE); + } + return 0L; +} + + +/********************************************************************* + * + * EM_SETMODIFY + * + */ +static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); - case EM_SETMODIFY: es->TextChanged = wParam; - break; - - case EM_SETPASSWORDCHAR: - es->PasswordChar = (char) wParam; - break; - - case EM_SETREADONLY: - 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: - case EM_SETRECTNP: - fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n"); - break; - - case EM_SETSEL: - EDIT_SetSelMsg(hwnd, wParam, lParam); - break; - - case EM_SETTABSTOPS: - lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam); - break; - - case EM_SETWORDBREAKPROC: - dprintf_edit(stddeb, "EM_SETWORDBREAKPROC, lParam=%08lx\n", - (DWORD)lParam); - es->WordBreakProc = (EDITWORDBREAKPROC)lParam; - break; - - case EM_UNDO: - lResult = EDIT_UndoMsg(hwnd); - break; - - case WM_GETDLGCODE: - lResult = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS; - break; - - case WM_CHAR: - EDIT_WM_Char(hwnd, wParam); - break; - - case WM_COPY: - EDIT_CopyToClipboard(hwnd); - EDIT_ClearSel(hwnd); - break; - - case WM_CREATE: - lResult = EDIT_WM_Create(hwnd, lParam); - break; - - case WM_CUT: - EDIT_CopyToClipboard(hwnd); - EDIT_DeleteSel(hwnd); - break; - - case WM_DESTROY: - free(es->textptrs); - free(es->CharWidths); - free(es->TabStops); - EDIT_HeapFree(hwnd, es->hText); - free( EDIT_GetEditState(hwnd) ); - break; - - case WM_ENABLE: - InvalidateRect(hwnd, NULL, FALSE); - break; - - case WM_GETTEXT: - textPtr = EDIT_HeapLock(hwnd, es->hText); - len = strlen( textPtr ); - if ((int)wParam > len) - { - strcpy((char *)PTR_SEG_TO_LIN(lParam), textPtr); - lResult = (LRESULT)len ; - } - EDIT_HeapUnlock(hwnd, es->hText); - break; - - case WM_GETTEXTLENGTH: - textPtr = EDIT_HeapLock(hwnd, es->hText); - lResult = (LRESULT)strlen(textPtr); - EDIT_HeapUnlock(hwnd, es->hText); - break; - - case WM_HSCROLL: - EDIT_WM_HScroll(hwnd, wParam, lParam); - break; - - case WM_KEYDOWN: - EDIT_WM_KeyDown(hwnd, wParam); - break; - - case WM_KILLFOCUS: - dprintf_edit(stddeb, "WM_KILLFOCUS\n"); - es->HaveFocus = FALSE; - DestroyCaret(); - if (SelMarked(es)) - if(GetWindowLong(hwnd,GWL_STYLE) & ES_NOHIDESEL) - EDIT_UpdateSel(hwnd); - else - EDIT_ClearSel(hwnd); - NOTIFY_PARENT(hwnd, EN_KILLFOCUS); - break; - - case WM_LBUTTONDOWN: - SetFocus(hwnd); - SetCapture(hwnd); - EDIT_WM_LButtonDown(hwnd, wParam, lParam); - break; - - case WM_LBUTTONUP: - if (GetCapture() != hwnd) break; - ReleaseCapture(); - ButtonDown = FALSE; - TextMarking = FALSE; - break; - - case WM_MOUSEMOVE: - if (es->HaveFocus) - EDIT_WM_MouseMove(hwnd, wParam, lParam); - break; - - case WM_MOVE: - break; - - case WM_NCCREATE: - lResult = EDIT_WM_NCCreate(hwnd, lParam); - break; - - case WM_PAINT: - EDIT_WM_Paint(hwnd); - break; - - case WM_PASTE: - EDIT_WM_Paste(hwnd); - break; - - case WM_SETFOCUS: - dprintf_edit(stddeb, "WM_SETFOCUS\n"); - es->HaveFocus = TRUE; - if (SelMarked(es)) EDIT_UpdateSel(hwnd); - CreateCaret(hwnd, 0, 2, es->txtht); - SetCaretPos(es->WndCol, es->WndRow * es->txtht); - es->CaretHidden = TRUE; - NOTIFY_PARENT(hwnd, EN_SETFOCUS); - break; - - case WM_SETFONT: - EDIT_WM_SetFont(hwnd, wParam, lParam); - break; -#if 0 - case WM_SETREDRAW: - dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n", - hwnd, wParam); - break; -#endif - case WM_SETTEXT: - EDIT_ClearDeletedText(hwnd); - EDIT_WM_SetText(hwnd, lParam); - break; - - case WM_SIZE: - EDIT_WM_Size(hwnd, wParam, lParam); - break; - - case WM_VSCROLL: - EDIT_WM_VScroll(hwnd, wParam, lParam); - break; - - case WM_LBUTTONDBLCLK: - EDIT_WM_LButtonDblClk(hwnd); - break; - - default: - lResult = DefWindowProc(hwnd, uMsg, wParam, lParam); - break; - } - - EDIT_CaretUpdate(hwnd); - - return lResult; + return 0L; } + +/********************************************************************* + * + * EM_SETPASSWORDCHAR + * + */ +static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + es->PasswordChar = (char)wParam; + return 0L; +} + + +/********************************************************************* + * + * EM_SETREADONLY + * + */ +static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + if ((BOOL)wParam) + wndPtr->dwStyle |= ES_READONLY; + else + wndPtr->dwStyle &= ~(DWORD)ES_READONLY; + return 0L; +} + + +/********************************************************************* + * + * EM_SETRECT + * + */ +static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n"); + return 0L; +} + + +/********************************************************************* + * + * EM_SETRECTNP + * + */ +static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n"); + return 0L; +} + + +/********************************************************************* + * + * EM_SETSEL + * + */ +static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + int ns = (INT)LOWORD(lParam); + int ne = (INT)HIWORD(lParam); + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int sl; + int el; + int sc; + int ec; + int elineindex; + int tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L); + RECT rc; + HRGN hRgn1, hRgn2; + HRGN oldRgn, newRgn; + + if (ns < 0) { + ne = e; + ns = e; + } else { + ns = MIN(ns, tl); + if (ne < 0) + ne = tl; + ne = MIN(ne, tl); + } + es->SelStart = ns; + es->SelEnd = ne; + if (wndPtr->hwndSelf == GetFocus()) { + el = EDIT_EM_LineFromChar(wndPtr, ne, 0L); + elineindex = EDIT_EM_LineIndex(wndPtr, el, 0L); + SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - elineindex), + EDIT_WndYFromLine(wndPtr, el)); + } + if (wParam) + EDIT_ScrollIntoView(wndPtr); + + /* + * Let's do some repainting + */ + ORDER_INT(s, e); + ORDER_INT(ns, ne); + if (EDIT_GetRedraw(wndPtr) && + !(((s == e) && (ns == ne)) || + ((ns == s) && (ne == e)))) { + /* Yes, there is something to paint */ + hRgn1 = CreateRectRgn(0, 0, 0, 0); + hRgn2 = CreateRectRgn(0, 0, 0, 0); + oldRgn = CreateRectRgn(0, 0, 0, 0); + newRgn = CreateRectRgn(0, 0, 0, 0); + /* Build the old selection region */ + sl = EDIT_EM_LineFromChar(wndPtr, s, 0L); + el = EDIT_EM_LineFromChar(wndPtr, e, 0L); + sc = s - EDIT_EM_LineIndex(wndPtr, sl, 0L); + ec = e - EDIT_EM_LineIndex(wndPtr, el, 0L); + if (sl == el) { + EDIT_GetLineRect(wndPtr, sl, sc, ec, &rc); + SetRectRgn(oldRgn, rc.left, rc.top, rc.right, rc.bottom); + } else { + EDIT_GetLineRect(wndPtr, sl, sc, -1, &rc); + SetRectRgn(hRgn1, rc.left, rc.top, rc.right, rc.bottom); + EDIT_GetLineRect(wndPtr, el, 0, ec, &rc); + SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom); + CombineRgn(oldRgn, hRgn1, hRgn2, RGN_OR); + if (el > sl + 1) { + EDIT_GetLineRect(wndPtr, sl + 1, 0, -1, &rc); + rc.bottom = rc.top + (rc.bottom - rc.top) * (el - sl - 1); + CombineRgn(hRgn1, oldRgn, 0, RGN_COPY); + SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom); + CombineRgn(oldRgn, hRgn1, hRgn2, RGN_OR); + } + } + /* Build the new selection region */ + sl = EDIT_EM_LineFromChar(wndPtr, ns, 0L); + el = EDIT_EM_LineFromChar(wndPtr, ne, 0L); + sc = ns - EDIT_EM_LineIndex(wndPtr, sl, 0L); + ec = ne - EDIT_EM_LineIndex(wndPtr, el, 0L); + if (sl == el) { + EDIT_GetLineRect(wndPtr, sl, sc, ec, &rc); + SetRectRgn(newRgn, rc.left, rc.top, rc.right, rc.bottom); + } else { + EDIT_GetLineRect(wndPtr, sl, sc, -1, &rc); + SetRectRgn(hRgn1, rc.left, rc.top, rc.right, rc.bottom); + EDIT_GetLineRect(wndPtr, el, 0, ec, &rc); + SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom); + CombineRgn(newRgn, hRgn1, hRgn2, RGN_OR); + if (el > sl + 1) { + EDIT_GetLineRect(wndPtr, sl + 1, 0, -1, &rc); + rc.bottom = rc.top + (rc.bottom - rc.top) * (el - sl - 1); + CombineRgn(hRgn1, newRgn, 0, RGN_COPY); + SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom); + CombineRgn(newRgn, hRgn1, hRgn2, RGN_OR); + } + } + /* Only difference needs painting */ + CombineRgn(hRgn1, oldRgn, newRgn, RGN_XOR); + /* Only part in formatting RECT needs painting */ + + InvalidateRgn(wndPtr->hwndSelf, hRgn1, FALSE); + DeleteObject(hRgn1); + DeleteObject(hRgn2); + DeleteObject(oldRgn); + DeleteObject(newRgn); + } + return -1L; +} + + +/********************************************************************* + * + * EM_SETTABSTOPS + * + */ +static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + if (!IsMultiLine(wndPtr)) + return 0L; + if (es->TabStops) + free(es->TabStops); + es->NumTabStops = wParam; + if (wParam == 0) + es->TabStops = NULL; + else { + es->TabStops = (unsigned short *)xmalloc(wParam * sizeof(unsigned short)); + memcpy(es->TabStops, (unsigned short *)PTR_SEG_TO_LIN(lParam), + wParam * sizeof(unsigned short)); + } + return 1L; +} + + +/********************************************************************* + * + * EM_SETWORDBREAKPROC + * + */ +static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + es->WordBreakProc = (EDITWORDBREAKPROC)lParam; + return 0L; +} + + +/********************************************************************* + * + * EM_UNDO + * + */ +static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return 0L; +} + + +/********************************************************************* + * + * WM_CHAR + * + */ +static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + char str[2]; + char c = (char)wParam; + + switch (c) { + case '\r': + case '\n': + if (IsMultiLine(wndPtr)) { + if (IsReadOnly(wndPtr)) { + EDIT_MoveHome(wndPtr, FALSE); + EDIT_MoveDownward(wndPtr, FALSE); + } else + EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n"); + } + break; + case '\t': + if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr)) + EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t"); + break; + default: + if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) { + str[0] = c; + str[1] = '\0'; + EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str); + } + break; + } + return 0L; +} + + +/********************************************************************* + * + * WM_CLEAR + * + */ +static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + char *text; + BOOL redraw; + + if (s != e) { + redraw = EDIT_GetRedraw(wndPtr); + EDIT_WM_SetRedraw(wndPtr, FALSE, 0L); + ORDER_INT(s, e); + text = EDIT_GetPointer(wndPtr); + strcpy(text + s, text + e); + EDIT_BuildLineDefs(wndPtr); + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, s)); + EDIT_EM_SetModify(wndPtr, TRUE, 0L); + EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE); + EDIT_WM_SetRedraw(wndPtr, redraw, 0L); + if (redraw) { + InvalidateRect(wndPtr->hwndSelf, NULL, TRUE); + EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE); + } + } + return -1L; +} + + +/********************************************************************* + * + * WM_COPY + * + */ +static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + HGLOBAL hdst; + char *text; + char *dst; + char *src; + int i; + + if (e == s) + return -1L; + ORDER_INT(s, e); + hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1)); + dst = GlobalLock(hdst); + text = EDIT_GetPointer(wndPtr); + src = text + s; + for (i = 0 ; i < e - s ; i++) + *dst++ = *src++; + *dst = '\0'; + GlobalUnlock(hdst); + OpenClipboard(wndPtr->hwndSelf); + EmptyClipboard(); + SetClipboardData(CF_TEXT, hdst); + CloseClipboard(); + return -1L; +} + + +/********************************************************************* + * + * WM_CREATE + * + */ +static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + CREATESTRUCT *cs = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam); + EDITSTATE *es; + char *windowName = NULL; + char *text; + + es = xmalloc(sizeof(EDITSTATE)); + memset(es, 0, sizeof(EDITSTATE)); + *(EDITSTATE **)wndPtr->wExtra = es; + + if (IsMultiLine(wndPtr)) { + es->BufLimit = BUFLIMIT_MULTI; + es->PasswordChar = '\0'; + } else { + es->BufLimit = BUFLIMIT_SINGLE; + es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0'; + } + + es->BufSize = IsMultiLine(wndPtr) ? BUFSTART_MULTI : BUFSTART_SINGLE; + if (cs->lpszName) + windowName = (char *)PTR_SEG_TO_LIN(cs->lpszName); + if (windowName) + es->BufSize = MAX(es->BufSize, strlen(windowName)); + es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1); + text = EDIT_GetPointer(wndPtr); + if (!text) { + fprintf(stderr, "edit: WM_CREATE: unable to heap buffer, please report !\n"); + return -1L; + } + if (windowName) + strcpy(text, windowName); + else + text[0] = '\0'; + + if (cs->style & WS_VSCROLL) + cs->style |= ES_AUTOVSCROLL; + if (cs->style & WS_HSCROLL) + cs->style |= ES_AUTOHSCROLL; + + /* remove the WS_CAPTION style if it has been set - this is really a */ + /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */ + if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME)) + cs->style ^= WS_DLGFRAME; + + EDIT_WM_SetFont(wndPtr, 0, 0L); + EDIT_WM_SetRedraw(wndPtr, TRUE, 0L); + return 0L; +} + + +/********************************************************************* + * + * WM_CUT + * + */ +static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDIT_WM_Copy(wndPtr, 0, 0L); + EDIT_WM_Clear(wndPtr, 0, 0L); + return -1L; +} + + +/********************************************************************* + * + * WM_DESTROY + * + */ +static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + free(es->LineDefs); + if (es->TabStops) + free(es->TabStops); + EDIT_ReleasePointer(wndPtr); + LOCAL_Free(wndPtr->hInstance, es->hBuf); + free(es); + *(EDITSTATE **)&wndPtr->wExtra = NULL; + return 0L; +} + + +/********************************************************************* + * + * WM_ENABLE + * + */ +static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return 0L; +} + + +/********************************************************************* + * + * WM_ERASEBKGND + * + */ +static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + HBRUSH hBrush; + RECT rc; + + hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam); + + GetClientRect(wndPtr->hwndSelf, &rc); + IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom); + GetClipBox((HDC)wParam, &rc); + /* + * FIXME: specs say that we should UnrealizeObject() the brush, + * but the specs of UnrealizeObject() say that we shouldn't + * unrealize a stock object. The default brush that + * DefWndProc() returns is ... a stock object. + */ + FillRect((HDC)wParam, &rc, hBrush); + return -1L; +} + + +/********************************************************************* + * + * WM_GETDLGCODE + * + */ +static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS; +} + + +/********************************************************************* + * + * WM_GETFONT + * + */ +static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + return (LRESULT)es->hFont; +} + + +/********************************************************************* + * + * WM_GETTEXT + * + */ +static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + char *text = EDIT_GetPointer(wndPtr); + int len; + LRESULT lResult = 0L; + + len = strlen(text); + if ((int)wParam > len) { + strcpy((char *)PTR_SEG_TO_LIN(lParam), text); + lResult = (LRESULT)len ; + } + return lResult; +} + + +/********************************************************************* + * + * WM_GETTEXTLENGTH + * + */ +static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + LRESULT ret; + char *text = EDIT_GetPointer(wndPtr); + + ret = (LRESULT)strlen(text); + return ret; +} + + +/********************************************************************* + * + * WM_HSCROLL + * + * FIXME: scrollbar code itself is broken, so this one is a hack. + * + */ +static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int wndwidth = EDIT_GetWndWidth(wndPtr); + int textwidth = EDIT_GetTextWidth(wndPtr); + int charwidth = EDIT_GetAveCharWidth(wndPtr); + int xoffset = EDIT_GetXOffset(wndPtr); + int dx = 0; + BOOL not = TRUE; + LRESULT ret = 0L; + + switch (wParam) { + case SB_LINELEFT: + dx = -charwidth; + break; + case SB_LINERIGHT: + dx = charwidth; + break; + case SB_PAGELEFT: + dx = -wndwidth / HSCROLL_FRACTION / charwidth * charwidth; + break; + case SB_PAGERIGHT: + dx = wndwidth / HSCROLL_FRACTION / charwidth * charwidth; + break; + case SB_LEFT: + dx = -xoffset; + break; + case SB_RIGHT: + dx = textwidth - xoffset; + break; + case SB_THUMBTRACK: +/* + * not = FALSE; + */ + case SB_THUMBPOSITION: + dx = LOWORD(lParam) * textwidth / 100 - xoffset; + break; + /* The next two are undocumented ! */ + case EM_GETTHUMB: + ret = textwidth ? MAKELONG(xoffset * 100 / textwidth, 0) : 0; + break; + case EM_LINESCROLL: + dx = LOWORD(lParam); + break; + case SB_ENDSCROLL: + default: + break; + } + if (dx) { + EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx)); + if (not) + EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL); + } + return ret; +} + + +/********************************************************************* + * + * WM_KEYDOWN + * + * Handling of special keys that don't produce a WM_CHAR + * (i.e. non-printable keys) & Backspace & Delete + * + */ +static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + BOOL shift; + BOOL control; + + if (GetKeyState(VK_MENU) & 0x8000) + return 0L; + + shift = GetKeyState(VK_SHIFT) & 0x8000; + control = GetKeyState(VK_CONTROL) & 0x8000; + + switch (wParam) { + case VK_LEFT: + case VK_UP: + if (IsMultiLine(wndPtr) && (wParam == VK_UP)) + EDIT_MoveUpward(wndPtr, shift); + else + if (control) + EDIT_MoveWordBackward(wndPtr, shift); + else + EDIT_MoveBackward(wndPtr, shift); + break; + case VK_RIGHT: + case VK_DOWN: + if (IsMultiLine(wndPtr) && (wParam == VK_DOWN)) + EDIT_MoveDownward(wndPtr, shift); + else if (control) + EDIT_MoveWordForward(wndPtr, shift); + else + EDIT_MoveForward(wndPtr, shift); + break; + case VK_HOME: + EDIT_MoveHome(wndPtr, shift); + break; + case VK_END: + EDIT_MoveEnd(wndPtr, shift); + break; + case VK_PRIOR: + if (IsMultiLine(wndPtr)) + EDIT_MovePageUp(wndPtr, shift); + break; + case VK_NEXT: + if (IsMultiLine(wndPtr)) + EDIT_MovePageDown(wndPtr, shift); + break; + case VK_BACK: + if (!IsReadOnly(wndPtr) && !control) + if (e != s) + EDIT_WM_Clear(wndPtr, 0, 0L); + else + EDIT_DelLeft(wndPtr); + break; + case VK_DELETE: + if (!IsReadOnly(wndPtr) && !(shift && control)) + if (e != s) { + if (shift) + EDIT_WM_Cut(wndPtr, 0, 0L); + else + EDIT_WM_Clear(wndPtr, 0, 0L); + } else { + if (shift) + EDIT_DelLeft(wndPtr); + else if (control) + EDIT_DelEnd(wndPtr); + else + EDIT_DelRight(wndPtr); + } + break; + case VK_INSERT: + if (shift) { + if (!IsReadOnly(wndPtr)) + EDIT_WM_Paste(wndPtr, 0, 0L); + } else if (control) + EDIT_WM_Copy(wndPtr, 0, 0L); + break; + } + return 0L; +} + + +/********************************************************************* + * + * WM_KILLFOCUS + * + */ +static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + DestroyCaret(); + if(!(wndPtr->dwStyle & ES_NOHIDESEL)) + EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0)); + EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS); + return 0L; +} + + +/********************************************************************* + * + * WM_LBUTTONDBLCLK + * + */ +static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int s; + int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + int l = EDIT_EM_LineFromChar(wndPtr, e, 0L); + int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L); + int linelength = EDIT_EM_LineLength(wndPtr, e, 0L); + char *text = EDIT_GetPointer(wndPtr); + + s = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex, e - lineindex, linelength, WB_LEFT); + e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex, e - lineindex, linelength, WB_RIGHT); + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); + return 0L; +} + + +/********************************************************************* + * + * WM_LBUTTONDOWN + * + */ +static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int l; + int s; + int e; + + SetFocus(wndPtr->hwndSelf); + SetCapture(wndPtr->hwndSelf); + l = EDIT_LineFromWndY(wndPtr, (INT)HIWORD(lParam)); + e = EDIT_EM_LineIndex(wndPtr, l ,0L) + + EDIT_ColFromWndX(wndPtr, l, (INT)LOWORD(lParam)); + if (GetKeyState(VK_SHIFT) & 0x8000) + s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); + else + s = e; + EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e)); + return 0L; +} + + +/********************************************************************* + * + * WM_LBUTTONUP + * + */ +static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + if (GetCapture() == wndPtr->hwndSelf) + ReleaseCapture(); + return 0L; +} + + +/********************************************************************* + * + * WM_MOUSEMOVE + * + */ +static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + int Line; + int Col; + int x = (INT)LOWORD(lParam); + + if (GetCapture() == wndPtr->hwndSelf) { + Line = EDIT_LineFromWndY(wndPtr, (INT)HIWORD(lParam)); + Line = MAX(Line, EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L)); + Line = MIN(Line, EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L) + EDIT_GetVisibleLineCount(wndPtr) - 1); + x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x)); + Col = EDIT_ColFromWndX(wndPtr, Line, x); + EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(es->SelStart, + EDIT_EM_LineIndex(wndPtr, Line, 0L) + Col)); + } + return 0L; +} + + +/********************************************************************* + * + * WM_PAINT + * + */ +static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + PAINTSTRUCT ps; + int i; + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + HDC hdc; + HFONT hFont; + HFONT oldFont = 0; + RECT rc; + RECT rcLine; + RECT rcRgn; + + hdc = BeginPaint(wndPtr->hwndSelf, &ps); + GetClientRect(wndPtr->hwndSelf, &rc); + IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); + hFont = EDIT_WM_GetFont(wndPtr, 0, 0L); + if (hFont) + oldFont = SelectObject(hdc, hFont); + EDIT_SEND_CTLCOLOR(wndPtr, hdc); + GetClipBox(hdc, &rcRgn); + for (i = firstvis ; i <= MIN(firstvis + EDIT_GetVisibleLineCount(wndPtr), firstvis + es->LineCount - 1) ; i++ ) { + EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine); + if (IntersectRect(&rc, &rcRgn, &rcLine)) + EDIT_PaintLine(wndPtr, hdc, i); + } + if (hFont) + SelectObject(hdc, oldFont); + EndPaint(wndPtr->hwndSelf, &ps); + return 0L; +} + + +/********************************************************************* + * + * WM_PASTE + * + */ +static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + HGLOBAL hsrc; + char *src; + + OpenClipboard(wndPtr->hwndSelf); + if ((hsrc = GetClipboardData(CF_TEXT))) { + src = (char *)GlobalLock(hsrc); + EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src); + GlobalUnlock(hsrc); + } + CloseClipboard(); + return -1L; +} + + +/********************************************************************* + * + * WM_SETCURSOR + * + */ +static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + if (LOWORD(lParam) == HTCLIENT) { + SetCursor(LoadCursor(0, IDC_IBEAM)); + return -1L; + } else + return 0L; +} + + +/********************************************************************* + * + * WM_SETFOCUS + * + */ +static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L); + + CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr)); + EDIT_EM_SetSel(wndPtr, FALSE, sel); + ShowCaret(wndPtr->hwndSelf); + EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS); + return 0L; +} + + +/********************************************************************* + * + * WM_SETFONT + * + */ +static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + TEXTMETRIC tm; + EDITSTATE *es = EDITSTATEPTR(wndPtr); + LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L); + HDC hdc; + HFONT oldFont = 0; + + es->hFont = (HFONT)wParam; + hdc = GetDC(wndPtr->hwndSelf); + if (es->hFont) + oldFont = SelectObject(hdc, es->hFont); + GetTextMetrics(hdc, &tm); + es->LineHeight = HIWORD(GetTextExtent(hdc, "", 0)); + es->AveCharWidth = tm.tmAveCharWidth; + if (es->hFont) + SelectObject(hdc, oldFont); + ReleaseDC(wndPtr->hwndSelf, hdc); + EDIT_BuildLineDefs(wndPtr); + if (lParam && EDIT_GetRedraw(wndPtr)) + InvalidateRect(wndPtr->hwndSelf, NULL, TRUE); + if (wndPtr->hwndSelf == GetFocus()) { + DestroyCaret(); + CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr)); + EDIT_EM_SetSel(wndPtr, FALSE, sel); + ShowCaret(wndPtr->hwndSelf); + } + return 0L; +} + + +/********************************************************************* + * + * WM_SETREDRAW + * + */ +static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDITSTATE *es = EDITSTATEPTR(wndPtr); + + es->Redraw = wParam ? TRUE : FALSE; + return 0L; +} + + +/********************************************************************* + * + * WM_SETTEXT + * + */ +static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(0, -1)); + EDIT_WM_Clear(wndPtr, 0, 0L); + if (lParam) + EDIT_EM_ReplaceSel(wndPtr, 0, lParam); + EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L); + EDIT_EM_SetModify(wndPtr, TRUE, 0L); + return 0L; +} + + +/********************************************************************* + * + * WM_SIZE + * + */ +static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + if (EDIT_GetRedraw(wndPtr) && + ((wParam == SIZE_MAXIMIZED) || + (wParam == SIZE_RESTORED))) + InvalidateRect(wndPtr->hwndSelf, NULL, TRUE); + return 0L; +} + + +/********************************************************************* + * + * WM_VSCROLL + * + * FIXME: scrollbar code itself is broken, so this one is a hack. + * + */ +static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) +{ + int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L); + int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); + int vislinecount = EDIT_GetVisibleLineCount(wndPtr); + int dy = 0; + BOOL not = TRUE; + LRESULT ret = 0L; + + switch (wParam) { + case SB_LINEUP: + dy = -1; + break; + case SB_LINEDOWN: + dy = 1; + break; + case SB_PAGEUP: + dy = -vislinecount; + break; + case SB_PAGEDOWN: + dy = vislinecount; + break; + case SB_TOP: + dy = -firstvis; + break; + case SB_BOTTOM: + dy = linecount - 1 - firstvis; + break; + case SB_THUMBTRACK: +/* + * not = FALSE; + */ + case SB_THUMBPOSITION: + dy = LOWORD(lParam) * (linecount - 1) / 100 - firstvis; + break; + /* The next two are undocumented ! */ + case EM_GETTHUMB: + ret = (linecount > 1) ? MAKELONG(firstvis * 100 / (linecount - 1), 0) : 0L; + break; + case EM_LINESCROLL: + dy = LOWORD(lParam); + break; + case SB_ENDSCROLL: + default: + break; + } + if (dy) { + EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0)); + if (not) + EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL); + } + return ret; +} diff --git a/controls/listbox.c b/controls/listbox.c index 21f66b4ed41..dbec947a578 100644 --- a/controls/listbox.c +++ b/controls/listbox.c @@ -2050,7 +2050,7 @@ BOOL DlgDirSelect( HWND hDlg, LPSTR lpStr, INT id ) dprintf_listbox( stddeb, "DlgDirSelect: %04x '%s' %d\n", hDlg, lpStr, id ); if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR) return FALSE; - SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, MAKE_SEGPTR(buffer) ); + SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, (LPARAM)MAKE_SEGPTR(buffer) ); if (buffer[0] == '[') /* drive or directory */ { if (buffer[1] == '-') /* drive */ diff --git a/controls/menu.c b/controls/menu.c index 33e58b38d95..7f09a8eac6e 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -1017,11 +1017,11 @@ static SEGPTR MENU_ParseResource( SEGPTR res, HMENU hMenu ) do { - flags = *(WORD *)PTR_SEG_TO_LIN( res ); + flags = GET_WORD( PTR_SEG_TO_LIN( res ) ); res += sizeof(WORD); if (!(flags & MF_POPUP)) { - id = *(WORD *)PTR_SEG_TO_LIN( res ); + id = GET_WORD( PTR_SEG_TO_LIN( res ) ); res += sizeof(WORD); } data = res; @@ -2315,7 +2315,7 @@ HMENU LoadMenu( HINSTANCE instance, SEGPTR name ) /* check for Win32 module */ instance = GetExePtr( instance ); - if(((NE_MODULE*)GlobalLock(instance))->flags & NE_FFLAGS_WIN32) + if (MODULE_GetPtr(instance)->flags & NE_FFLAGS_WIN32) return WIN32_LoadMenuA(instance,PTR_SEG_TO_LIN(name)); if (!(hRsrc = FindResource( instance, name, RT_MENU ))) return 0; diff --git a/debugger/dbg.y b/debugger/dbg.y index b1ae0e48391..e809a379298 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -217,6 +217,18 @@ void mode_command(int newmode) } + +/*********************************************************************** + * DEBUG_EnterDebugger + * + * Force an entry into the debugger. + */ +void DEBUG_EnterDebugger(void) +{ + kill( getpid(), SIGHUP ); +} + + void wine_debug( int signal, struct sigcontext_struct *regs ) { static int loaded_symbols = 0; @@ -248,6 +260,12 @@ void wine_debug( int signal, struct sigcontext_struct *regs ) addr.off = EIP_reg(DEBUG_context); DBG_FIX_ADDR_SEG( &addr, 0 ); + /* Put the display in a correct state */ + + XUngrabPointer( display, CurrentTime ); + XUngrabServer( display ); + XFlush( display ); + if (!addr.seg) newmode = 32; else newmode = (GET_SEL_FLAGS(addr.seg) & LDT_FLAGS_32BIT) ? 32 : 16; diff --git a/debugger/hash.c b/debugger/hash.c index c21c0d088d0..daeda4a282c 100644 --- a/debugger/hash.c +++ b/debugger/hash.c @@ -217,7 +217,7 @@ void DEBUG_LoadEntryPoints(void) for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry)) { - if (!(pModule = (NE_MODULE *)GlobalLock( entry.hModule ))) continue; + if (!(pModule = MODULE_GetPtr( entry.hModule ))) continue; name = (unsigned char *)pModule + pModule->name_table; diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec index f2053745289..e58e0cfabde 100644 --- a/if1632/kernel32.spec +++ b/if1632/kernel32.spec @@ -261,7 +261,7 @@ base 1 0256 stub GetPrivateProfileStringW 0257 stdcall GetProcAddress(long long) WIN32_GetProcAddress 0258 stub GetProcessAffinityMask -0259 return GetProcessHeap 0 0 +0259 stdcall GetProcessHeap() GetProcessHeap 0260 stub GetProcessHeaps 0261 stub GetProcessShutdownParameters 0262 stub GetProcessTimes @@ -338,18 +338,18 @@ base 1 0332 stub GlobalUnlock 0333 stub GlobalWire 0334 stdcall HeapAlloc(long long long) HeapAlloc -0335 stub HeapCompact +0335 stdcall HeapCompact(long long) HeapCompact 0336 stdcall HeapCreate(long long long) HeapCreate -0337 stub HeapDestroy -0338 stub HeapFree -0339 stub HeapLock -0340 stub HeapReAlloc -0341 stub HeapSize -0342 stub HeapUnlock -0343 stub HeapValidate -0344 stub HeapWalk +0337 stdcall HeapDestroy(long) HeapDestroy +0338 stdcall HeapFree(long long ptr) HeapFree +0339 stdcall HeapLock(long) HeapLock +0340 stdcall HeapReAlloc(long long ptr long) HeapReAlloc +0341 stdcall HeapSize(long long ptr) HeapSize +0342 stdcall HeapUnlock(long) HeapUnlock +0343 stdcall HeapValidate(long long ptr) HeapValidate +0344 stdcall HeapWalk(long ptr) HeapWalk 0345 stub InitAtomTable -0346 stdcall InitializeCriticalSection(ptr) InitializeCriticalSection +0346 stdcall InitializeCriticalSection(ptr) InitializeCriticalSection 0347 stub InterlockedDecrement 0348 stub InterlockedExchange 0349 stub InterlockedIncrement diff --git a/include/debug.h b/include/debug.h index 1d721918a2e..0fe20026b23 100644 --- a/include/debug.h +++ b/include/debug.h @@ -47,6 +47,7 @@ #undef DEBUG_GDI #undef DEBUG_GLOBAL #undef DEBUG_GRAPHICS +#undef DEBUG_HEAP #undef DEBUG_HOOK #undef DEBUG_ICON #undef DEBUG_INT @@ -126,6 +127,7 @@ #define DEBUG_GDI #define DEBUG_GLOBAL #define DEBUG_GRAPHICS +#define DEBUG_HEAP #define DEBUG_HOOK #define DEBUG_ICON #define DEBUG_INT @@ -331,6 +333,11 @@ short debug_msg_enabled[]={ #else 0, #endif +#ifdef DEBUG_HEAP + 1, +#else + 0, +#endif #ifdef DEBUG_HOOK 1, #else @@ -967,8 +974,21 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_hook if(!debug_msg_enabled[31]) ; else fprintf -#define debugging_hook debug_msg_enabled[31] +#define dprintf_heap if(!debug_msg_enabled[31]) ; else fprintf +#define debugging_heap debug_msg_enabled[31] +#else +#ifdef DEBUG_HEAP +#define dprintf_heap fprintf +#define debugging_heap 1 +#else +#define dprintf_heap while(0) fprintf +#define debugging_heap 0 +#endif +#endif + +#ifdef DEBUG_RUNTIME +#define dprintf_hook if(!debug_msg_enabled[32]) ; else fprintf +#define debugging_hook debug_msg_enabled[32] #else #ifdef DEBUG_HOOK #define dprintf_hook fprintf @@ -980,8 +1000,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_icon if(!debug_msg_enabled[32]) ; else fprintf -#define debugging_icon debug_msg_enabled[32] +#define dprintf_icon if(!debug_msg_enabled[33]) ; else fprintf +#define debugging_icon debug_msg_enabled[33] #else #ifdef DEBUG_ICON #define dprintf_icon fprintf @@ -993,8 +1013,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_int if(!debug_msg_enabled[33]) ; else fprintf -#define debugging_int debug_msg_enabled[33] +#define dprintf_int if(!debug_msg_enabled[34]) ; else fprintf +#define debugging_int debug_msg_enabled[34] #else #ifdef DEBUG_INT #define dprintf_int fprintf @@ -1006,8 +1026,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_key if(!debug_msg_enabled[34]) ; else fprintf -#define debugging_key debug_msg_enabled[34] +#define dprintf_key if(!debug_msg_enabled[35]) ; else fprintf +#define debugging_key debug_msg_enabled[35] #else #ifdef DEBUG_KEY #define dprintf_key fprintf @@ -1019,8 +1039,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_keyboard if(!debug_msg_enabled[35]) ; else fprintf -#define debugging_keyboard debug_msg_enabled[35] +#define dprintf_keyboard if(!debug_msg_enabled[36]) ; else fprintf +#define debugging_keyboard debug_msg_enabled[36] #else #ifdef DEBUG_KEYBOARD #define dprintf_keyboard fprintf @@ -1032,8 +1052,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_ldt if(!debug_msg_enabled[36]) ; else fprintf -#define debugging_ldt debug_msg_enabled[36] +#define dprintf_ldt if(!debug_msg_enabled[37]) ; else fprintf +#define debugging_ldt debug_msg_enabled[37] #else #ifdef DEBUG_LDT #define dprintf_ldt fprintf @@ -1045,8 +1065,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_listbox if(!debug_msg_enabled[37]) ; else fprintf -#define debugging_listbox debug_msg_enabled[37] +#define dprintf_listbox if(!debug_msg_enabled[38]) ; else fprintf +#define debugging_listbox debug_msg_enabled[38] #else #ifdef DEBUG_LISTBOX #define dprintf_listbox fprintf @@ -1058,8 +1078,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_local if(!debug_msg_enabled[38]) ; else fprintf -#define debugging_local debug_msg_enabled[38] +#define dprintf_local if(!debug_msg_enabled[39]) ; else fprintf +#define debugging_local debug_msg_enabled[39] #else #ifdef DEBUG_LOCAL #define dprintf_local fprintf @@ -1071,8 +1091,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mci if(!debug_msg_enabled[39]) ; else fprintf -#define debugging_mci debug_msg_enabled[39] +#define dprintf_mci if(!debug_msg_enabled[40]) ; else fprintf +#define debugging_mci debug_msg_enabled[40] #else #ifdef DEBUG_MCI #define dprintf_mci fprintf @@ -1084,8 +1104,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mcianim if(!debug_msg_enabled[40]) ; else fprintf -#define debugging_mcianim debug_msg_enabled[40] +#define dprintf_mcianim if(!debug_msg_enabled[41]) ; else fprintf +#define debugging_mcianim debug_msg_enabled[41] #else #ifdef DEBUG_MCIANIM #define dprintf_mcianim fprintf @@ -1097,8 +1117,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mciwave if(!debug_msg_enabled[41]) ; else fprintf -#define debugging_mciwave debug_msg_enabled[41] +#define dprintf_mciwave if(!debug_msg_enabled[42]) ; else fprintf +#define debugging_mciwave debug_msg_enabled[42] #else #ifdef DEBUG_MCIWAVE #define dprintf_mciwave fprintf @@ -1110,8 +1130,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mdi if(!debug_msg_enabled[42]) ; else fprintf -#define debugging_mdi debug_msg_enabled[42] +#define dprintf_mdi if(!debug_msg_enabled[43]) ; else fprintf +#define debugging_mdi debug_msg_enabled[43] #else #ifdef DEBUG_MDI #define dprintf_mdi fprintf @@ -1123,8 +1143,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_menu if(!debug_msg_enabled[43]) ; else fprintf -#define debugging_menu debug_msg_enabled[43] +#define dprintf_menu if(!debug_msg_enabled[44]) ; else fprintf +#define debugging_menu debug_msg_enabled[44] #else #ifdef DEBUG_MENU #define dprintf_menu fprintf @@ -1136,8 +1156,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_message if(!debug_msg_enabled[44]) ; else fprintf -#define debugging_message debug_msg_enabled[44] +#define dprintf_message if(!debug_msg_enabled[45]) ; else fprintf +#define debugging_message debug_msg_enabled[45] #else #ifdef DEBUG_MESSAGE #define dprintf_message fprintf @@ -1149,8 +1169,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_metafile if(!debug_msg_enabled[45]) ; else fprintf -#define debugging_metafile debug_msg_enabled[45] +#define dprintf_metafile if(!debug_msg_enabled[46]) ; else fprintf +#define debugging_metafile debug_msg_enabled[46] #else #ifdef DEBUG_METAFILE #define dprintf_metafile fprintf @@ -1162,8 +1182,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_midi if(!debug_msg_enabled[46]) ; else fprintf -#define debugging_midi debug_msg_enabled[46] +#define dprintf_midi if(!debug_msg_enabled[47]) ; else fprintf +#define debugging_midi debug_msg_enabled[47] #else #ifdef DEBUG_MIDI #define dprintf_midi fprintf @@ -1175,8 +1195,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mmio if(!debug_msg_enabled[47]) ; else fprintf -#define debugging_mmio debug_msg_enabled[47] +#define dprintf_mmio if(!debug_msg_enabled[48]) ; else fprintf +#define debugging_mmio debug_msg_enabled[48] #else #ifdef DEBUG_MMIO #define dprintf_mmio fprintf @@ -1188,8 +1208,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mmsys if(!debug_msg_enabled[48]) ; else fprintf -#define debugging_mmsys debug_msg_enabled[48] +#define dprintf_mmsys if(!debug_msg_enabled[49]) ; else fprintf +#define debugging_mmsys debug_msg_enabled[49] #else #ifdef DEBUG_MMSYS #define dprintf_mmsys fprintf @@ -1201,8 +1221,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_mmtime if(!debug_msg_enabled[49]) ; else fprintf -#define debugging_mmtime debug_msg_enabled[49] +#define dprintf_mmtime if(!debug_msg_enabled[50]) ; else fprintf +#define debugging_mmtime debug_msg_enabled[50] #else #ifdef DEBUG_MMTIME #define dprintf_mmtime fprintf @@ -1214,8 +1234,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_module if(!debug_msg_enabled[50]) ; else fprintf -#define debugging_module debug_msg_enabled[50] +#define dprintf_module if(!debug_msg_enabled[51]) ; else fprintf +#define debugging_module debug_msg_enabled[51] #else #ifdef DEBUG_MODULE #define dprintf_module fprintf @@ -1227,8 +1247,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_msg if(!debug_msg_enabled[51]) ; else fprintf -#define debugging_msg debug_msg_enabled[51] +#define dprintf_msg if(!debug_msg_enabled[52]) ; else fprintf +#define debugging_msg debug_msg_enabled[52] #else #ifdef DEBUG_MSG #define dprintf_msg fprintf @@ -1240,8 +1260,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_nonclient if(!debug_msg_enabled[52]) ; else fprintf -#define debugging_nonclient debug_msg_enabled[52] +#define dprintf_nonclient if(!debug_msg_enabled[53]) ; else fprintf +#define debugging_nonclient debug_msg_enabled[53] #else #ifdef DEBUG_NONCLIENT #define dprintf_nonclient fprintf @@ -1253,8 +1273,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_ole if(!debug_msg_enabled[53]) ; else fprintf -#define debugging_ole debug_msg_enabled[53] +#define dprintf_ole if(!debug_msg_enabled[54]) ; else fprintf +#define debugging_ole debug_msg_enabled[54] #else #ifdef DEBUG_OLE #define dprintf_ole fprintf @@ -1266,8 +1286,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_palette if(!debug_msg_enabled[54]) ; else fprintf -#define debugging_palette debug_msg_enabled[54] +#define dprintf_palette if(!debug_msg_enabled[55]) ; else fprintf +#define debugging_palette debug_msg_enabled[55] #else #ifdef DEBUG_PALETTE #define dprintf_palette fprintf @@ -1279,8 +1299,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_profile if(!debug_msg_enabled[55]) ; else fprintf -#define debugging_profile debug_msg_enabled[55] +#define dprintf_profile if(!debug_msg_enabled[56]) ; else fprintf +#define debugging_profile debug_msg_enabled[56] #else #ifdef DEBUG_PROFILE #define dprintf_profile fprintf @@ -1292,8 +1312,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_prop if(!debug_msg_enabled[56]) ; else fprintf -#define debugging_prop debug_msg_enabled[56] +#define dprintf_prop if(!debug_msg_enabled[57]) ; else fprintf +#define debugging_prop debug_msg_enabled[57] #else #ifdef DEBUG_PROP #define dprintf_prop fprintf @@ -1305,8 +1325,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_reg if(!debug_msg_enabled[57]) ; else fprintf -#define debugging_reg debug_msg_enabled[57] +#define dprintf_reg if(!debug_msg_enabled[58]) ; else fprintf +#define debugging_reg debug_msg_enabled[58] #else #ifdef DEBUG_REG #define dprintf_reg fprintf @@ -1318,8 +1338,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_region if(!debug_msg_enabled[58]) ; else fprintf -#define debugging_region debug_msg_enabled[58] +#define dprintf_region if(!debug_msg_enabled[59]) ; else fprintf +#define debugging_region debug_msg_enabled[59] #else #ifdef DEBUG_REGION #define dprintf_region fprintf @@ -1331,8 +1351,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_relay if(!debug_msg_enabled[59]) ; else fprintf -#define debugging_relay debug_msg_enabled[59] +#define dprintf_relay if(!debug_msg_enabled[60]) ; else fprintf +#define debugging_relay debug_msg_enabled[60] #else #ifdef DEBUG_RELAY #define dprintf_relay fprintf @@ -1344,8 +1364,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_resource if(!debug_msg_enabled[60]) ; else fprintf -#define debugging_resource debug_msg_enabled[60] +#define dprintf_resource if(!debug_msg_enabled[61]) ; else fprintf +#define debugging_resource debug_msg_enabled[61] #else #ifdef DEBUG_RESOURCE #define dprintf_resource fprintf @@ -1357,8 +1377,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_scroll if(!debug_msg_enabled[61]) ; else fprintf -#define debugging_scroll debug_msg_enabled[61] +#define dprintf_scroll if(!debug_msg_enabled[62]) ; else fprintf +#define debugging_scroll debug_msg_enabled[62] #else #ifdef DEBUG_SCROLL #define dprintf_scroll fprintf @@ -1370,8 +1390,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_selector if(!debug_msg_enabled[62]) ; else fprintf -#define debugging_selector debug_msg_enabled[62] +#define dprintf_selector if(!debug_msg_enabled[63]) ; else fprintf +#define debugging_selector debug_msg_enabled[63] #else #ifdef DEBUG_SELECTOR #define dprintf_selector fprintf @@ -1383,8 +1403,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_sem if(!debug_msg_enabled[63]) ; else fprintf -#define debugging_sem debug_msg_enabled[63] +#define dprintf_sem if(!debug_msg_enabled[64]) ; else fprintf +#define debugging_sem debug_msg_enabled[64] #else #ifdef DEBUG_SEM #define dprintf_sem fprintf @@ -1396,8 +1416,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_shm if(!debug_msg_enabled[64]) ; else fprintf -#define debugging_shm debug_msg_enabled[64] +#define dprintf_shm if(!debug_msg_enabled[65]) ; else fprintf +#define debugging_shm debug_msg_enabled[65] #else #ifdef DEBUG_SHM #define dprintf_shm fprintf @@ -1409,8 +1429,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_stress if(!debug_msg_enabled[65]) ; else fprintf -#define debugging_stress debug_msg_enabled[65] +#define dprintf_stress if(!debug_msg_enabled[66]) ; else fprintf +#define debugging_stress debug_msg_enabled[66] #else #ifdef DEBUG_STRESS #define dprintf_stress fprintf @@ -1422,8 +1442,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_syscolor if(!debug_msg_enabled[66]) ; else fprintf -#define debugging_syscolor debug_msg_enabled[66] +#define dprintf_syscolor if(!debug_msg_enabled[67]) ; else fprintf +#define debugging_syscolor debug_msg_enabled[67] #else #ifdef DEBUG_SYSCOLOR #define dprintf_syscolor fprintf @@ -1435,8 +1455,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_task if(!debug_msg_enabled[67]) ; else fprintf -#define debugging_task debug_msg_enabled[67] +#define dprintf_task if(!debug_msg_enabled[68]) ; else fprintf +#define debugging_task debug_msg_enabled[68] #else #ifdef DEBUG_TASK #define dprintf_task fprintf @@ -1448,8 +1468,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_text if(!debug_msg_enabled[68]) ; else fprintf -#define debugging_text debug_msg_enabled[68] +#define dprintf_text if(!debug_msg_enabled[69]) ; else fprintf +#define debugging_text debug_msg_enabled[69] #else #ifdef DEBUG_TEXT #define dprintf_text fprintf @@ -1461,8 +1481,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_timer if(!debug_msg_enabled[69]) ; else fprintf -#define debugging_timer debug_msg_enabled[69] +#define dprintf_timer if(!debug_msg_enabled[70]) ; else fprintf +#define debugging_timer debug_msg_enabled[70] #else #ifdef DEBUG_TIMER #define dprintf_timer fprintf @@ -1474,8 +1494,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_toolhelp if(!debug_msg_enabled[70]) ; else fprintf -#define debugging_toolhelp debug_msg_enabled[70] +#define dprintf_toolhelp if(!debug_msg_enabled[71]) ; else fprintf +#define debugging_toolhelp debug_msg_enabled[71] #else #ifdef DEBUG_TOOLHELP #define dprintf_toolhelp fprintf @@ -1487,8 +1507,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_utility if(!debug_msg_enabled[71]) ; else fprintf -#define debugging_utility debug_msg_enabled[71] +#define dprintf_utility if(!debug_msg_enabled[72]) ; else fprintf +#define debugging_utility debug_msg_enabled[72] #else #ifdef DEBUG_UTILITY #define dprintf_utility fprintf @@ -1500,8 +1520,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_vxd if(!debug_msg_enabled[72]) ; else fprintf -#define debugging_vxd debug_msg_enabled[72] +#define dprintf_vxd if(!debug_msg_enabled[73]) ; else fprintf +#define debugging_vxd debug_msg_enabled[73] #else #ifdef DEBUG_VXD #define dprintf_vxd fprintf @@ -1513,8 +1533,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_win if(!debug_msg_enabled[73]) ; else fprintf -#define debugging_win debug_msg_enabled[73] +#define dprintf_win if(!debug_msg_enabled[74]) ; else fprintf +#define debugging_win debug_msg_enabled[74] #else #ifdef DEBUG_WIN #define dprintf_win fprintf @@ -1526,8 +1546,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_win32 if(!debug_msg_enabled[74]) ; else fprintf -#define debugging_win32 debug_msg_enabled[74] +#define dprintf_win32 if(!debug_msg_enabled[75]) ; else fprintf +#define debugging_win32 debug_msg_enabled[75] #else #ifdef DEBUG_WIN32 #define dprintf_win32 fprintf @@ -1539,8 +1559,8 @@ extern short debug_msg_enabled[]; #endif #ifdef DEBUG_RUNTIME -#define dprintf_winsock if(!debug_msg_enabled[75]) ; else fprintf -#define debugging_winsock debug_msg_enabled[75] +#define dprintf_winsock if(!debug_msg_enabled[76]) ; else fprintf +#define debugging_winsock debug_msg_enabled[76] #else #ifdef DEBUG_WINSOCK #define dprintf_winsock fprintf @@ -1586,6 +1606,7 @@ static char *debug_msg_name[] = { "gdi", "global", "graphics", + "heap", "hook", "icon", "int", diff --git a/include/debugger.h b/include/debugger.h index 1f1a7afffb2..866e2029af3 100644 --- a/include/debugger.h +++ b/include/debugger.h @@ -111,6 +111,7 @@ extern void DEBUG_InfoStack(void); extern void DEBUG_BackTrace(void); /* debugger/dbg.y */ +extern void DEBUG_EnterDebugger(void); extern void wine_debug( int signal, struct sigcontext_struct * regs ); #endif /* DEBUGGER_H */ diff --git a/include/dialog.h b/include/dialog.h index 2eb2d8f9721..e835b5b141e 100644 --- a/include/dialog.h +++ b/include/dialog.h @@ -33,34 +33,27 @@ typedef struct } DIALOGINFO; - /* Dialog template header */ -typedef struct -{ - DWORD style; - BYTE nbItems WINE_PACKED; - WORD x WINE_PACKED; - WORD y WINE_PACKED; - WORD cx WINE_PACKED; - WORD cy WINE_PACKED; -} DLGTEMPLATEHEADER; - - /* Dialog control header */ typedef struct { + DWORD style; WORD x; WORD y; WORD cx; WORD cy; WORD id; - DWORD style WINE_PACKED; } DLGCONTROLHEADER; /* Dialog template */ typedef struct { - DLGTEMPLATEHEADER header; + DWORD style; + WORD nbItems; + WORD x; + WORD y; + WORD cx; + WORD cy; SEGPTR menuName; SEGPTR className; SEGPTR caption; diff --git a/include/handle32.h b/include/handle32.h index 08ab132d8b0..6ebbaa2a36e 100644 --- a/include/handle32.h +++ b/include/handle32.h @@ -15,7 +15,7 @@ typedef struct { unsigned long magic; -} KERNEL_OBJECT, *HANDLE32; +} KERNEL_OBJECT; typedef struct { KERNEL_OBJECT common; diff --git a/include/module.h b/include/module.h index 01561f1ae5f..01c78407826 100644 --- a/include/module.h +++ b/include/module.h @@ -8,6 +8,7 @@ #define _WINE_MODULE_H #include "wintypes.h" +#include "pe_image.h" #ifndef WINELIB #pragma pack(1) @@ -16,49 +17,45 @@ /* In-memory module structure. See 'Windows Internals' p. 219 */ typedef struct { - WORD magic; /* 'NE' signature */ - WORD count; /* Usage count */ - WORD entry_table; /* Near ptr to entry table */ - HMODULE next; /* Selector to next module */ - WORD dgroup_entry; /* Near ptr to segment entry for DGROUP */ - WORD fileinfo; /* Near ptr to file info (OFSTRUCT) */ - WORD flags; /* Module flags */ - WORD dgroup; /* Logical segment for DGROUP */ - WORD heap_size; /* Initial heap size */ - WORD stack_size; /* Initial stack size */ - WORD ip; /* Initial ip */ - WORD cs; /* Initial cs (logical segment) */ - WORD sp; /* Initial stack pointer */ - WORD ss; /* Initial ss (logical segment) */ - WORD seg_count; /* Number of segments in segment table */ - WORD modref_count; /* Number of module references */ - WORD nrname_size; /* Size of non-resident names table */ - WORD seg_table; /* Near ptr to segment table */ - WORD res_table; /* Near ptr to resource table */ - WORD name_table; /* Near ptr to resident names table */ - WORD modref_table; /* Near ptr to module reference table */ - WORD import_table; /* Near ptr to imported names table */ - DWORD nrname_fpos; /* File offset of non-resident names table */ - WORD moveable_entries; /* Number of moveable entries in entry table */ - WORD alignment; /* Alignment shift count */ - WORD truetype; /* Set to 2 if TrueType font */ - BYTE os_flags; /* Operating system flags */ - BYTE misc_flags; /* Misc. flags */ - HANDLE dlls_to_init; /* List of DLLs to initialize */ - HANDLE nrname_handle; /* Handle to non-resident name table in memory */ - WORD min_swap_area; /* Min. swap area size */ - WORD expected_version; /* Expected Windows version */ - WORD self_loading_sel; /* Selector used for self-loading apps. procs */ + WORD magic; /* 00 'NE' signature */ + WORD count; /* 02 Usage count */ + WORD entry_table; /* 04 Near ptr to entry table */ + HMODULE next; /* 06 Selector to next module */ + WORD dgroup_entry; /* 08 Near ptr to segment entry for DGROUP */ + WORD fileinfo; /* 0a Near ptr to file info (OFSTRUCT) */ + WORD flags; /* 0c Module flags */ + WORD dgroup; /* 0e Logical segment for DGROUP */ + WORD heap_size; /* 10 Initial heap size */ + WORD stack_size; /* 12 Initial stack size */ + WORD ip; /* 14 Initial ip */ + WORD cs; /* 16 Initial cs (logical segment) */ + WORD sp; /* 18 Initial stack pointer */ + WORD ss; /* 1a Initial ss (logical segment) */ + WORD seg_count; /* 1c Number of segments in segment table */ + WORD modref_count; /* 1e Number of module references */ + WORD nrname_size; /* 20 Size of non-resident names table */ + WORD seg_table; /* 22 Near ptr to segment table */ + WORD res_table; /* 24 Near ptr to resource table */ + WORD name_table; /* 26 Near ptr to resident names table */ + WORD modref_table; /* 28 Near ptr to module reference table */ + WORD import_table; /* 2a Near ptr to imported names table */ + DWORD nrname_fpos; /* 2c File offset of non-resident names table */ + WORD moveable_entries; /* 30 Number of moveable entries in entry table*/ + WORD alignment; /* 32 Alignment shift count */ + WORD truetype; /* 34 Set to 2 if TrueType font */ + BYTE os_flags; /* 36 Operating system flags */ + BYTE misc_flags; /* 37 Misc. flags */ + HANDLE dlls_to_init; /* 38 List of DLLs to initialize */ + HANDLE nrname_handle; /* 3a Handle to non-resident name table */ + WORD min_swap_area; /* 3c Min. swap area size */ + WORD expected_version; /* 3e Expected Windows version */ + /* From here, these are extra fields not present in normal Windows */ + PE_MODULE *pe_module; /* 40 PE module handle for Win32 modules */ + HMODULE self; /* 44 Handle for this module */ + WORD self_loading_sel; /* 46 Selector used for self-loading apps. */ } NE_MODULE; - /* Extra module info appended to NE_MODULE for Win32 modules */ -typedef struct -{ - DWORD pe_module; -} NE_WIN32_EXTRAINFO; - - /* In-memory segment table */ typedef struct { @@ -115,6 +112,7 @@ typedef struct #endif extern BOOL MODULE_Init(void); +extern NE_MODULE *MODULE_GetPtr( HMODULE hModule ); extern void MODULE_DumpModule( HMODULE hmodule ); extern void MODULE_WalkModules(void); extern int MODULE_OpenFile( HMODULE hModule ); @@ -128,7 +126,7 @@ extern FARPROC MODULE_GetWndProcEntry16( const char *name ); extern FARPROC MODULE_GetWndProcEntry32( const char *name ); extern BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ); -extern void NE_FixupPrologs( HMODULE hModule ); +extern void NE_FixupPrologs( NE_MODULE *pModule ); extern void NE_InitializeDLLs( HMODULE hModule ); #endif /* _WINE_MODULE_H */ diff --git a/include/pe_image.h b/include/pe_image.h index e97d4187e0e..f5274818850 100644 --- a/include/pe_image.h +++ b/include/pe_image.h @@ -18,6 +18,8 @@ struct pe_data { int resource_offset; /* offset to resource typedirectory in file */ }; +typedef struct pe_data PE_MODULE; + extern int PE_unloadImage(HMODULE hModule); extern void my_wcstombs(char * result, u_short * source, int len); diff --git a/include/stddebug.h b/include/stddebug.h index 452812a04cc..7852551ace6 100644 --- a/include/stddebug.h +++ b/include/stddebug.h @@ -107,6 +107,7 @@ #undef DEBUG_GDI #undef DEBUG_GLOBAL #undef DEBUG_GRAPHICS +#undef DEBUG_HEAP #undef DEBUG_HOOK #undef DEBUG_ICON #undef DEBUG_INT @@ -186,6 +187,7 @@ #define DEBUG_GDI #define DEBUG_GLOBAL #define DEBUG_GRAPHICS +#define DEBUG_HEAP #define DEBUG_HOOK #define DEBUG_ICON #define DEBUG_INT diff --git a/include/winbase.h b/include/winbase.h index 38f5e3ced5d..66d8e1ab816 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1,5 +1,5 @@ -#ifndef _WINBASE_H -#define _WINBASE_H +#ifndef __WINE_WINBASE_H +#define __WINE_WINBASE_H @@ -19,12 +19,6 @@ #define WAIT_ABANDONED_0 STATUS_ABANDONED_WAIT_0 #define WAIT_TIMEOUT STATUS_TIMEOUT -#define MEM_COMMIT 0x1000 -#define MEM_RESERVE 0x2000 -#define MEM_TOPDOWN 0x100000 - -#define MEM_RELEASE 0x8000 - #define PAGE_NOACCESS 0x01 #define PAGE_READONLY 0x02 #define PAGE_READWRITE 0x04 @@ -36,11 +30,14 @@ #define PAGE_GUARD 0x100 #define PAGE_NOCACHE 0x200 -HANDLE WINAPI OpenProcess(DWORD access, BOOL inherit, DWORD id); -int WINAPI GetCurrentProcessId(void); -int WINAPI TerminateProcess(HANDLE h, int ret); - -WINAPI void * VirtualAlloc (void *addr,DWORD size,DWORD type,DWORD protect); +#define MEM_COMMIT 0x00001000 +#define MEM_RESERVE 0x00002000 +#define MEM_DECOMMIT 0x00004000 +#define MEM_RELEASE 0x00008000 +#define MEM_FREE 0x00010000 +#define MEM_PRIVATE 0x00020000 +#define MEM_MAPPED 0x00040000 +#define MEM_TOP_DOWN 0x00100000 struct _EXCEPTION_POINTERS; @@ -105,8 +102,6 @@ typedef struct int ss; } exception_info; -#endif - /*DWORD WINAPI GetVersion( void );*/ @@ -122,3 +117,27 @@ HACCEL WINAPI LoadAcceleratorsA( HINSTANCE, const char *); #define FreeModule(hLibModule) FreeLibrary((hLibModule)) #define MakeProcInstance(lpProc,hInstance) (lpProc) #define FreeProcInstance(lpProc) (lpProc) + + +WINAPI void DeleteCriticalSection(CRITICAL_SECTION *lpCrit); +WINAPI void EnterCriticalSection(CRITICAL_SECTION *lpCrit); +WINAPI int GetCurrentProcessId(void); +WINAPI HANDLE32 GetProcessHeap(void); +WINAPI LPVOID HeapAlloc(HANDLE32,DWORD,DWORD); +WINAPI DWORD HeapCompact(HANDLE32,DWORD); +WINAPI HANDLE32 HeapCreate(DWORD,DWORD,DWORD); +WINAPI BOOL HeapDestroy(HANDLE32); +WINAPI BOOL HeapFree(HANDLE32,DWORD,LPVOID); +WINAPI BOOL HeapLock(HANDLE32); +WINAPI LPVOID HeapReAlloc(HANDLE32,DWORD,LPVOID,DWORD); +WINAPI DWORD HeapSize(HANDLE32,DWORD,LPVOID); +WINAPI BOOL HeapUnlock(HANDLE32); +WINAPI BOOL HeapValidate(HANDLE32,DWORD,LPVOID); +WINAPI void InitializeCriticalSection(CRITICAL_SECTION *lpCrit); +WINAPI void LeaveCriticalSection(CRITICAL_SECTION *lpCrit); +WINAPI HANDLE OpenProcess(DWORD access, BOOL inherit, DWORD id); +WINAPI int TerminateProcess(HANDLE h, int ret); +WINAPI LPVOID VirtualAlloc(LPVOID addr,DWORD size,DWORD type,DWORD protect); +WINAPI BOOL VirtualFree( LPVOID addr, DWORD size, DWORD type ); + +#endif /* __WINE_WINBASE_H */ diff --git a/include/winnt.h b/include/winnt.h new file mode 100644 index 00000000000..b72a44d8c38 --- /dev/null +++ b/include/winnt.h @@ -0,0 +1,23 @@ +/* + * Win32 definitions for Windows NT + * + * Copyright 1996 Alexandre Julliard + */ + +#ifndef __WINE_WINNT_H +#define __WINE_WINNT_H + +/* Heap flags */ +#define HEAP_NO_SERIALIZE 0x00000001 +#define HEAP_GROWABLE 0x00000002 +#define HEAP_GENERATE_EXCEPTIONS 0x00000004 +#define HEAP_ZERO_MEMORY 0x00000008 +#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010 +#define HEAP_TAIL_CHECKING_ENABLED 0x00000020 +#define HEAP_FREE_CHECKING_ENABLED 0x00000040 +#define HEAP_DISABLE_COALESCE_ON_FREE 0x00000080 +#define HEAP_CREATE_ALIGN_16 0x00010000 +#define HEAP_CREATE_ENABLE_TRACING 0x00020000 + + +#endif /* __WINE_WINNT_H */ diff --git a/include/wintypes.h b/include/wintypes.h index 8f539260704..9430f56c438 100644 --- a/include/wintypes.h +++ b/include/wintypes.h @@ -43,6 +43,7 @@ typedef DWORD SEGPTR; #endif /* WINELIB32 */ typedef UINT HANDLE; +typedef DWORD HANDLE32; typedef UINT WPARAM; typedef LONG LPARAM; typedef LONG LRESULT; @@ -163,6 +164,23 @@ typedef FARPROC HOOKPROC; #define SELECTOROF(ptr) (HIWORD(ptr)) #define OFFSETOF(ptr) (LOWORD(ptr)) +#if !defined(WINELIB) || defined(__i386__) +#define PUT_WORD(ptr,w) (*(WORD *)(ptr) = (w)) +#define GET_WORD(ptr) (*(WORD *)(ptr)) +#define PUT_DWORD(ptr,dw) (*(DWORD *)(ptr) = (dw)) +#define GET_DWORD(ptr) (*(DWORD *)(ptr)) +#else +#define PUT_WORD(ptr,w) (*(BYTE *)(ptr) = LOBYTE(w), \ + *((BYTE *)(ptr) + 1) = HIBYTE(w)) +#define GET_WORD(ptr) ((WORD)(*(BYTE *)(ptr) | \ + (WORD)(*((BYTE *)(ptr)+1) << 8))) +#define PUT_DWORD(ptr,dw) (PUT_WORD((ptr),LOWORD(dw)), \ + PUT_WORD((WORD *)(ptr)+1,HIWORD(dw))) +#define GET_DWORD(ptr) ((DWORD)(GET_WORD(ptr) | \ + ((DWORD)GET_WORD((WORD *)(ptr)+1) << 16))) +#endif /* !WINELIB || __i386__ */ + + #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif @@ -171,13 +189,4 @@ typedef FARPROC HOOKPROC; #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -#ifndef DONT_DEFINE_min_AND_max -#ifndef min -#define min(a,b) MIN(a,b) -#endif -#ifndef max -#define max(a,b) MAX(a,b) -#endif -#endif - #endif /* __WINE_WINTYPES_H */ diff --git a/library/miscstubs.c b/library/miscstubs.c index 8ed3f2470d4..846f702a8e5 100644 --- a/library/miscstubs.c +++ b/library/miscstubs.c @@ -207,3 +207,8 @@ WNDPROC MODULE_GetWndProcEntry32( char *name ) { return MODULE_GetWndProcEntry16( name ); } + +void DEBUG_EnterDebugger(void) +{ +} + diff --git a/loader/module.c b/loader/module.c index 060c286f95e..128c05a4b34 100644 --- a/loader/module.c +++ b/loader/module.c @@ -72,10 +72,11 @@ static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force ) dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n", table->name, hModule ); pModule = (NE_MODULE *)GlobalLock( hModule ); + pModule->self = hModule; if (pModule->flags & NE_FFLAGS_WIN32) { - ((NE_WIN32_EXTRAINFO*)(pModule+1))->pe_module = (DWORD)table; + pModule->pe_module = (PE_MODULE *)table; } else /* Win16 module */ { @@ -126,6 +127,18 @@ BOOL MODULE_Init(void) } +/*********************************************************************** + * MODULE_GetPtr + */ +NE_MODULE *MODULE_GetPtr( HMODULE hModule ) +{ + NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule ); + if (!pModule || (pModule->magic != NE_SIGNATURE) || + (pModule->self != hModule)) return NULL; + return pModule; +} + + /*********************************************************************** * MODULE_DumpModule */ @@ -135,9 +148,9 @@ void MODULE_DumpModule( HMODULE hmodule ) SEGTABLEENTRY *pSeg; BYTE *pstr; WORD *pword; - NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule ); + NE_MODULE *pModule; - if (!pModule || (pModule->magic != NE_SIGNATURE)) + if (!(pModule = MODULE_GetPtr( hmodule ))) { fprintf( stderr, "**** %04x is not a module handle\n", hmodule ); return; @@ -156,7 +169,7 @@ void MODULE_DumpModule( HMODULE hmodule ) pModule->os_flags, pModule->min_swap_area, pModule->expected_version ); if (pModule->flags & NE_FFLAGS_WIN32) - printf( "PE module=%08x\n", (unsigned int)NE_WIN32_MODULE(pModule) ); + printf( "PE module=%08x\n", (unsigned int)pModule->pe_module ); /* Dump the file info */ @@ -276,8 +289,8 @@ void MODULE_WalkModules(void) fprintf( stderr, "Module Flags Name\n" ); while (hModule) { - NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule ); - if (!pModule || (pModule->magic != NE_SIGNATURE)) + NE_MODULE *pModule = MODULE_GetPtr( hModule ); + if (!pModule) { fprintf( stderr, "**** Bad module %04x in list\n", hModule ); return; @@ -304,7 +317,7 @@ int MODULE_OpenFile( HMODULE hModule ) hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n", hModule, hCachedModule, cachedfd ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1; + if (!(pModule = MODULE_GetPtr( hModule ))) return -1; if (hCachedModule == hModule) return cachedfd; close( cachedfd ); hCachedModule = hModule; @@ -370,7 +383,7 @@ static BOOL MODULE_CreateSegments( HMODULE hModule ) NE_MODULE *pModule; int i, minsize; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE; + if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE; pSegment = NE_SEG_TABLE( pModule ); for (i = 1; i <= pModule->seg_count; i++, pSegment++) { @@ -402,7 +415,7 @@ static HINSTANCE MODULE_GetInstance( HMODULE hModule ) SEGTABLEENTRY *pSegment; NE_MODULE *pModule; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (pModule->dgroup == 0) return hModule; pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1; @@ -422,7 +435,7 @@ HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params ) int minsize; HINSTANCE hNewInstance, hPrevInstance; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (pModule->dgroup == 0) return hModule; pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1; @@ -501,10 +514,17 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) if (!hModule) return (HMODULE)11; /* invalid exe */ FarSetOwner( hModule, hModule ); pModule = (NE_MODULE *)GlobalLock( hModule ); - memcpy( pModule, &ne_header, sizeof(NE_MODULE) ); + memcpy( pModule, &ne_header, sizeof(ne_header) ); pModule->count = 0; + pModule->pe_module = NULL; + pModule->self = hModule; + pModule->self_loading_sel = 0; pData = (BYTE *)(pModule + 1); + /* Clear internal Wine flags in case they are set in the EXE file */ + + pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32); + /* Read the fast-load area */ if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD) @@ -524,10 +544,6 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) } } - /* Clear internal Wine flags in case they are set in the EXE file */ - - pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32); - /* Store the filename information */ pModule->fileinfo = (int)pData - (int)pModule; @@ -556,7 +572,11 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) } free( buffer ); } - else return (HMODULE)11; /* invalid exe */ + else + { + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } /* Get the resource table */ @@ -575,7 +595,11 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) pModule->name_table = (int)pData - (int)pModule; if (!READ( ne_header.rname_tab_offset, ne_header.moduleref_tab_offset - ne_header.rname_tab_offset, - pData )) return (HMODULE)11; /* invalid exe */ + pData )) + { + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset; /* Get the module references table */ @@ -595,7 +619,11 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) pModule->import_table = (int)pData - (int)pModule; if (!READ( ne_header.iname_tab_offset, ne_header.entry_tab_offset - ne_header.iname_tab_offset, - pData )) return (HMODULE)11; /* invalid exe */ + pData )) + { + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset; /* Get the entry table */ @@ -603,7 +631,11 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) pModule->entry_table = (int)pData - (int)pModule; if (!READ( ne_header.entry_tab_offset, ne_header.entry_tab_length, - pData )) return (HMODULE)11; /* invalid exe */ + pData )) + { + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } pData += ne_header.entry_tab_length; /* Get the non-resident names table */ @@ -612,11 +644,20 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) { pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length, hModule, FALSE, FALSE, FALSE ); - if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */ + if (!pModule->nrname_handle) + { + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } buffer = GlobalLock( pModule->nrname_handle ); _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 */ + != ne_header.nrname_tab_length) + { + GlobalFree( pModule->nrname_handle ); + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } } else pModule->nrname_handle = 0; @@ -627,14 +668,19 @@ HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs ) pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT, (pModule->modref_count+1)*sizeof(HMODULE), hModule, FALSE, FALSE, FALSE ); - if (!pModule->dlls_to_init) return (HMODULE)11; /* invalid exe */ + if (!pModule->dlls_to_init) + { + if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle ); + GlobalFree( hModule ); + return (HMODULE)11; /* invalid exe */ + } } else pModule->dlls_to_init = 0; - if (debugging_module) MODULE_DumpModule( hModule ); pModule->next = hFirstModule; hFirstModule = hModule; return hModule; +#undef READ } @@ -649,7 +695,7 @@ WORD MODULE_GetOrdinal( HMODULE hModule, const char *name ) BYTE len; NE_MODULE *pModule; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n", hModule, name ); @@ -714,7 +760,7 @@ SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal ) BYTE *p; WORD sel, offset; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; p = (BYTE *)pModule + pModule->entry_table; while (*p && (curOrdinal + *p <= ordinal)) @@ -764,7 +810,7 @@ BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset ) WORD curOrdinal = 1; BYTE *p; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE; + if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE; p = (BYTE *)pModule + pModule->entry_table; while (*p && (curOrdinal + *p <= ordinal)) @@ -809,7 +855,7 @@ LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal ) register char *cpnt; NE_MODULE *pModule; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; /* First search the resident names */ @@ -876,7 +922,7 @@ LPSTR MODULE_GetModuleName( HMODULE hModule ) BYTE *p, len; static char buffer[10]; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL; + if (!(pModule = MODULE_GetPtr( hModule ))) return NULL; p = (BYTE *)pModule + pModule->name_table; len = MIN( *p, 8 ); memcpy( buffer, p + 1, len ); @@ -890,10 +936,9 @@ LPSTR MODULE_GetModuleName( HMODULE hModule ) */ void MODULE_RegisterModule( HMODULE hModule ) { - NE_MODULE *pModule; - pModule = (NE_MODULE *)GlobalLock( hModule ); - pModule->next = hFirstModule; - hFirstModule = hModule; + NE_MODULE *pModule = MODULE_GetPtr( hModule ); + pModule->next = hFirstModule; + hFirstModule = hModule; } /********************************************************************** @@ -915,7 +960,7 @@ HMODULE MODULE_FindModule( LPCSTR path ) while(hModule) { - NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule) break; modulepath = NE_MODULE_NAME(pModule); if (!(modulename = strrchr( modulepath, '\\' ))) @@ -945,18 +990,22 @@ static void MODULE_FreeModule( HMODULE hModule ) HMODULE *pModRef; int i; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return; + if (!(pModule = MODULE_GetPtr( hModule ))) return; if (pModule->flags & NE_FFLAGS_BUILTIN) return; /* Can't free built-in module */ /* FIXME: should call the exit code for the library here */ + /* Clear magic number just in case */ + + pModule->magic = pModule->self = 0; + /* Remove it from the linked list */ hPrevModule = &hFirstModule; while (*hPrevModule && (*hPrevModule != hModule)) { - hPrevModule = &((NE_MODULE *)GlobalLock( *hPrevModule ))->next; + hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next; } if (*hPrevModule) *hPrevModule = pModule->next; @@ -1038,7 +1087,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) return hModule; } _lclose( hFile ); - pModule = (NE_MODULE *)GlobalLock( hModule ); + pModule = MODULE_GetPtr( hModule ); /* Allocate the segments for this module */ @@ -1086,7 +1135,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) } else /* Increment the reference count of the DLL */ { - NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef ); + NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef ); if (pOldDLL) pOldDLL->count++; } } @@ -1171,7 +1220,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) /* Fixup the functions prologs */ - NE_FixupPrologs( hModule ); + NE_FixupPrologs( pModule ); /* Make sure the usage count is 1 on the first loading of */ /* the module, even if it contains circular DLL references */ @@ -1180,7 +1229,7 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) } else { - pModule = (NE_MODULE *)GlobalLock( hModule ); + pModule = MODULE_GetPtr( hModule ); hPrevInstance = MODULE_GetInstance( hModule ); hInstance = MODULE_CreateInstance( hModule, params ); if (hInstance != hPrevInstance) /* not a library */ @@ -1191,7 +1240,8 @@ HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock ) hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) ); pModule = (NE_MODULE *)GlobalLock( hModule ); pModule->count = 1; - pModule->magic = 0x454e; + pModule->magic = NE_SIGNATURE; + pModule->self = hModule; hPrevInstance = 0; hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock ); #endif /* WINELIB */ @@ -1218,7 +1268,7 @@ BOOL FreeModule( HANDLE hModule ) NE_MODULE *pModule; hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE; + if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE; dprintf_module( stddeb, "FreeModule: %s count %d\n", MODULE_GetModuleName(hModule), pModule->count ); @@ -1250,7 +1300,7 @@ int GetModuleUsage( HANDLE hModule ) NE_MODULE *pModule; hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n", hModule, pModule->count ); return pModule->count; @@ -1265,7 +1315,7 @@ int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize ) NE_MODULE *pModule; hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize ); dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName ); return strlen(lpFileName); @@ -1486,9 +1536,8 @@ FARPROC GetProcAddress( HANDLE hModule, SEGPTR name ) */ WORD GetExpWinVer( HMODULE hModule ) { - NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule ); - - return pModule->expected_version; + NE_MODULE *pModule = MODULE_GetPtr( hModule ); + return pModule ? pModule->expected_version : 0; } @@ -1510,7 +1559,7 @@ BOOL ModuleNext( MODULEENTRY *lpme ) NE_MODULE *pModule; if (!lpme->wNext) return FALSE; - if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE; + if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE; strncpy( lpme->szModule, (char *)pModule + pModule->name_table, MAX_MODULE_NAME ); lpme->szModule[MAX_MODULE_NAME] = '\0'; diff --git a/loader/ne_image.c b/loader/ne_image.c index 8ae9004bfd8..2fcd8f98345 100644 --- a/loader/ne_image.c +++ b/loader/ne_image.c @@ -49,7 +49,7 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) int ordinal, additive; unsigned short *sp; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE; + if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE; pSegTable = NE_SEG_TABLE( pModule ); pSeg = pSegTable + segnum - 1; pModuleTable = NE_MODULE_TABLE( pModule ); @@ -171,7 +171,7 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) address = MODULE_GetEntryPoint( module, ordinal ); if (!address) { - NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module ); + NE_MODULE *pTarget = MODULE_GetPtr( module ); if (!pTarget) fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n", module, rep->target1, @@ -187,7 +187,7 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) } if (debugging_fixup) { - NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module ); + NE_MODULE *pTarget = MODULE_GetPtr( module ); fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1, *((BYTE *)pTarget + pTarget->name_table), *((BYTE *)pTarget + pTarget->name_table), @@ -208,7 +208,7 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) if (!address) { - NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module ); + NE_MODULE *pTarget = MODULE_GetPtr( module ); fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n", *((BYTE *)pTarget + pTarget->name_table), *((BYTE *)pTarget + pTarget->name_table), @@ -216,7 +216,7 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) } if (debugging_fixup) { - NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module ); + NE_MODULE *pTarget = MODULE_GetPtr( module ); fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1, *((BYTE *)pTarget + pTarget->name_table), *((BYTE *)pTarget + pTarget->name_table), @@ -347,23 +347,21 @@ BOOL NE_LoadSegment( HMODULE hModule, WORD segnum ) * * Fixup the exported functions prologs. */ -void NE_FixupPrologs( HMODULE hModule ) +void NE_FixupPrologs( NE_MODULE *pModule ) { #ifdef WINELIB fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n"); #else - NE_MODULE *pModule; SEGTABLEENTRY *pSegTable; WORD dgroup = 0; WORD sel; BYTE *p, *fixup_ptr, count; - pModule = (NE_MODULE *)GlobalLock( hModule ); pSegTable = NE_SEG_TABLE(pModule); if (pModule->flags & NE_FFLAGS_SINGLEDATA) dgroup = pSegTable[pModule->dgroup-1].selector; - dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule ); + dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self ); p = (BYTE *)pModule + pModule->entry_table; while (*p) { @@ -455,10 +453,11 @@ static BOOL NE_InitDLL( HMODULE hModule ) * es:si command line (always 0) */ - pModule = (NE_MODULE *)GlobalLock( hModule ); + if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE; pSegTable = NE_SEG_TABLE( pModule ); - if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/ + if (!(pModule->flags & NE_FFLAGS_LIBMODULE) || + (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/ if (!pModule->cs) return TRUE; /* no initialization code */ if (!(pModule->flags & NE_FFLAGS_SINGLEDATA)) @@ -509,7 +508,7 @@ void NE_InitializeDLLs( HMODULE hModule ) NE_MODULE *pModule; HMODULE *pDLL; - pModule = (NE_MODULE *)GlobalLock( hModule ); + if (!(pModule = MODULE_GetPtr( hModule ))) return; if (pModule->flags & NE_FFLAGS_WIN32) { PE_InitializeDLLs(hModule); diff --git a/loader/ne_resource.c b/loader/ne_resource.c index e7e1a6e2136..7e45089fbdd 100644 --- a/loader/ne_resource.c +++ b/loader/ne_resource.c @@ -43,7 +43,7 @@ static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId ) DWORD ret = 0; int count; - pModule = (NE_MODULE *)GlobalLock( hModule ); + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2); for (; pTypeInfo->type_id != 0; pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) + @@ -139,11 +139,10 @@ static HRSRC NE_FindResourceFromType( NE_MODULE *pModule, */ HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId ) { - NE_MODULE *pModule; NE_TYPEINFO *pTypeInfo; HRSRC hRsrc; - pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule || !pModule->res_table) return 0; pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2); @@ -217,11 +216,10 @@ HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId ) */ HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size ) { - NE_MODULE *pModule; NE_NAMEINFO *pNameInfo=NULL; WORD sizeShift; - pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule || !pModule->res_table) return 0; sizeShift = *(WORD *)((char *)pModule + pModule->res_table); #ifndef WINELIB @@ -238,11 +236,10 @@ HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size ) */ int NE_AccessResource( HMODULE hModule, HRSRC hRsrc ) { - NE_MODULE *pModule; NE_NAMEINFO *pNameInfo=NULL; int fd; - pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule || !pModule->res_table) return -1; #ifndef WINELIB pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc); @@ -262,11 +259,10 @@ int NE_AccessResource( HMODULE hModule, HRSRC hRsrc ) */ DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc ) { - NE_MODULE *pModule; NE_NAMEINFO *pNameInfo=NULL; WORD sizeShift; - pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule || !pModule->res_table) return 0; sizeShift = *(WORD *)((char *)pModule + pModule->res_table); #ifndef WINELIB @@ -281,12 +277,11 @@ DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc ) */ HGLOBAL NE_LoadResource( HMODULE hModule, HRSRC hRsrc ) { - NE_MODULE *pModule; NE_NAMEINFO *pNameInfo=NULL; WORD sizeShift; int fd; - pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule || !pModule->res_table) return 0; #ifndef WINELIB pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc); @@ -328,12 +323,11 @@ SEGPTR NE_LockResource( HMODULE hModule, HGLOBAL handle ) */ BOOL NE_FreeResource( HMODULE hModule, HGLOBAL handle ) { - NE_MODULE *pModule; NE_TYPEINFO *pTypeInfo; NE_NAMEINFO *pNameInfo; WORD count; - pModule = (NE_MODULE *)GlobalLock( hModule ); + NE_MODULE *pModule = MODULE_GetPtr( hModule ); if (!pModule || !pModule->res_table) return FALSE; pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2); while (pTypeInfo->type_id) diff --git a/loader/pe_image.c b/loader/pe_image.c index ad822886b78..79789b7e2de 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -34,6 +34,8 @@ #include "debug.h" #include "xmalloc.h" +static HANDLE32 ProcessHeap; /* FIXME: should be in process database */ + void my_wcstombs(char * result, u_short * source, int len) { while(len--) { @@ -136,20 +138,19 @@ static DWORD PE_FindExportedFunction(struct pe_data *pe, char* funcName) DWORD PE_GetProcAddress(HMODULE hModule, char* function) { NE_MODULE *pModule; - struct pe_data *pe; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0; if (pModule->flags & NE_FFLAGS_BUILTIN) { - BUILTIN_DLL *dll = (BUILTIN_DLL *)NE_WIN32_MODULE(pModule); + BUILTIN_DLL *dll = (BUILTIN_DLL *)pModule->pe_module; if(HIWORD(function)) return RELAY32_GetEntryPoint(dll,function,0); else return RELAY32_GetEntryPoint(dll,0,(int)function); } - if (!(pe = NE_WIN32_MODULE(pModule))) return 0; - return PE_FindExportedFunction( pe, function ); + if (!pModule->pe_module) return 0; + return PE_FindExportedFunction( pModule->pe_module, function ); } void fixup_imports(struct pe_data *pe, HMODULE hModule) @@ -286,7 +287,7 @@ static void calc_vma_size(struct pe_data *pe) pe->pe_seg[i].NumberOfRelocations, pe->pe_seg[i].NumberOfLinenumbers, pe->pe_seg[i].Characteristics); - pe->vma_size = max(pe->vma_size, + pe->vma_size = MAX(pe->vma_size, pe->pe_seg[i].Virtual_Address + pe->pe_seg[i].Size_Of_Raw_Data); } @@ -535,10 +536,9 @@ void InitTask(struct sigcontext_struct context); HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params ) { - struct pe_data *pe; + PE_MODULE *pe; int size, of_size; NE_MODULE *pModule; - NE_WIN32_EXTRAINFO *pExtraInfo; SEGTABLEENTRY *pSegment; char *pStr; DWORD cts; @@ -554,8 +554,6 @@ HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params ) of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(ofs->szPathName) + 1; size = sizeof(NE_MODULE) + - /* extra module info */ - sizeof(NE_WIN32_EXTRAINFO) + /* loaded file info */ of_size + /* segment table: DS,CS */ @@ -586,18 +584,16 @@ HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params ) pModule->seg_count=1; pModule->modref_count=0; pModule->nrname_size=0; - pModule->fileinfo=sizeof(NE_MODULE) + sizeof(NE_WIN32_EXTRAINFO); + pModule->fileinfo=sizeof(NE_MODULE); pModule->os_flags=NE_OSFLAGS_WINDOWS; pModule->expected_version=0x30A; - - /* Set extra info */ - pExtraInfo = (NE_WIN32_EXTRAINFO *)(pModule + 1); + pModule->self = hModule; /* Set loaded file information */ - memcpy( pExtraInfo + 1, ofs, of_size ); - ((OFSTRUCT *)(pExtraInfo+1))->cBytes = of_size - 1; + memcpy( pModule + 1, ofs, of_size ); + ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1; - pSegment=(SEGTABLEENTRY*)((char*)(pExtraInfo + 1) + of_size); + pSegment=(SEGTABLEENTRY*)((char*)(pModule + 1) + of_size); pModule->seg_table=pModule->dgroup_entry=(int)pSegment-(int)pModule; pSegment->size=0; pSegment->flags=NE_SEGFLAGS_DATA; @@ -627,7 +623,7 @@ HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params ) pe = PE_LoadImage( fd, hModule, mz_header.ne_offset ); - pExtraInfo->pe_module = (DWORD)pe; + pModule->pe_module = pe; pModule->heap_size=0x1000; pModule->stack_size=0xE000; @@ -638,6 +634,7 @@ HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params ) if ((pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL)) { /* PE_InitDLL(hModule); */ } else { + ProcessHeap = HeapCreate( 0, 0x10000, 0 ); TASK_CreateTask(hModule,hInstance,0, params->hEnvironment,(LPSTR)PTR_SEG_TO_LIN(params->cmdLine), *((WORD*)PTR_SEG_TO_LIN(params->showCmd)+1)); @@ -646,6 +643,11 @@ HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params ) return hInstance; } +HANDLE32 GetProcessHeap(void) +{ + return ProcessHeap; +} + int USER_InitApp(HINSTANCE hInstance); void PE_InitTEB(int hTEB); @@ -653,19 +655,19 @@ void PE_Win32CallToStart(struct sigcontext_struct context) { int fs; HMODULE hModule; + NE_MODULE *pModule; struct pe_data *pe; dprintf_win32(stddeb,"Going to start Win32 program\n"); InitTask(context); hModule = GetExePtr( GetCurrentTask() ); + pModule = MODULE_GetPtr( hModule ); USER_InitApp( hModule ); fs=(int)GlobalAlloc(GHND,0x10000); PE_InitTEB(fs); - pe = NE_WIN32_MODULE( (NE_MODULE *)GlobalLock(hModule) ); __asm__ __volatile__("movw %w0,%%fs"::"r" (fs)); -/* ((void(*)())(pe->load_addr+pe->pe_header->opt_coff.AddressOfEntryPoint))(); */ - CallTaskStart32( (FARPROC)(pe->load_addr + - pe->pe_header->opt_coff.AddressOfEntryPoint) ); + CallTaskStart32( (FARPROC)(pModule->pe_module->load_addr + + pModule->pe_module->pe_header->opt_coff.AddressOfEntryPoint) ); } int PE_UnloadImage( HMODULE hModule ) @@ -678,11 +680,13 @@ int PE_UnloadImage( HMODULE hModule ) static void PE_InitDLL(HMODULE hModule) { NE_MODULE *pModule; - struct pe_data *pe; + PE_MODULE *pe; + hModule = GetExePtr(hModule); - if (!(pModule = (NE_MODULE *)GlobalLock(hModule))) return; - if (!(pModule->flags & NE_FFLAGS_WIN32)) return; - if (!(pe = NE_WIN32_MODULE(pModule))) return; + if (!(pModule = MODULE_GetPtr(hModule))) return; + if (!(pModule->flags & NE_FFLAGS_WIN32) || !(pe = pModule->pe_module)) + return; + /* FIXME: What are the correct values for parameters 2 and 3? */ /* Is this a library? */ @@ -726,7 +730,7 @@ void PE_InitializeDLLs(HMODULE hModule) { NE_MODULE *pModule; HMODULE *pDLL; - pModule = (NE_MODULE *)GlobalLock( GetExePtr(hModule) ); + pModule = MODULE_GetPtr( GetExePtr(hModule) ); if (pModule->dlls_to_init) { HANDLE to_init = pModule->dlls_to_init; diff --git a/loader/resource.c b/loader/resource.c index 0de3993e588..b6a45493214 100644 --- a/loader/resource.c +++ b/loader/resource.c @@ -52,7 +52,7 @@ HRSRC FindResource( HMODULE hModule, SEGPTR name, SEGPTR type ) dprintf_resource( stddeb, " name=" ); PrintId( name ); dprintf_resource( stddeb, "\n" ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; #ifndef WINELIB if (pModule->flags & NE_FFLAGS_WIN32) { @@ -77,7 +77,7 @@ HGLOBAL LoadResource( HMODULE hModule, HRSRC hRsrc ) dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n", hModule, hRsrc ); if (!hRsrc) return 0; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; #ifndef WINELIB if (pModule->flags & NE_FFLAGS_WIN32) { @@ -104,7 +104,7 @@ SEGPTR WIN16_LockResource( HGLOBAL handle ) dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle ); if (!handle) return (SEGPTR)0; hModule = GetExePtr( handle ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (pModule->flags & NE_FFLAGS_WIN32) { fprintf(stderr,"Don't know how to LockResource() for Win32 module\n"); @@ -126,7 +126,7 @@ LPVOID LockResource( HGLOBAL handle ) dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle ); if (!handle) return NULL; hModule = GetExePtr( handle ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (pModule->flags & NE_FFLAGS_WIN32) { fprintf(stderr,"Don't know how to LockResource() for Win32 module\n"); @@ -151,7 +151,7 @@ BOOL FreeResource( HGLOBAL handle ) dprintf_resource(stddeb, "FreeResource: handle=%04x\n", handle ); if (!handle) return FALSE; hModule = GetExePtr( handle ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (pModule->flags & NE_FFLAGS_WIN32) { fprintf(stderr,"Don't know how to FreeResource() for Win32 module\n"); @@ -175,7 +175,7 @@ INT AccessResource( HINSTANCE hModule, HRSRC hRsrc ) dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n", hModule, hRsrc ); if (!hRsrc) return 0; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; #ifndef WINELIB if (pModule->flags & NE_FFLAGS_WIN32) { @@ -199,7 +199,7 @@ DWORD SizeofResource( HMODULE hModule, HRSRC hRsrc ) hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n", hModule, hRsrc ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; #ifndef WINELIB if (pModule->flags & NE_FFLAGS_WIN32) { @@ -224,7 +224,7 @@ HGLOBAL AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size ) dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n", hModule, hRsrc, size ); if (!hRsrc) return 0; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; #ifndef WINELIB if (pModule->flags & NE_FFLAGS_WIN32) { diff --git a/loader/signal.c b/loader/signal.c index d9b72ab6869..e7f9ea24bbf 100644 --- a/loader/signal.c +++ b/loader/signal.c @@ -113,9 +113,6 @@ static void win_fault(int signal, int code, struct sigcontext *context) } } - XUngrabPointer(display, CurrentTime); - XUngrabServer(display); - XFlush(display); wine_debug( signal, context ); /* Enter our debugger */ } diff --git a/loader/task.c b/loader/task.c index 0a2a3b8d19f..7ddac311bb4 100644 --- a/loader/task.c +++ b/loader/task.c @@ -162,7 +162,7 @@ static HANDLE TASK_CreateDOSEnvironment(void) /* Now add the program name */ *p++ = '\0'; - *(WORD *)p = 1; + PUT_WORD( p, 1 ); p += sizeof(WORD); GetSystemDirectory( p, sysdirlen ); strcat( p, "\\" ); @@ -329,7 +329,7 @@ static void TASK_CallToStart(void) { int cs_reg, ds_reg, ip_reg; TDB *pTask = (TDB *)GlobalLock( hCurrentTask ); - NE_MODULE *pModule = (NE_MODULE *)GlobalLock( pTask->hModule ); + NE_MODULE *pModule = MODULE_GetPtr( pTask->hModule ); SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); /* Registers at initialization must be: @@ -387,7 +387,7 @@ HTASK TASK_CreateTask( HMODULE hModule, HANDLE hInstance, HANDLE hPrevInstance, extern DWORD CALLTO16_RetAddr_word; #endif - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; pSegTable = NE_SEG_TABLE( pModule ); /* Allocate the task structure */ @@ -759,7 +759,7 @@ void InitTask( struct sigcontext_struct context ) EAX_reg(&context) = 0; #endif if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return; - if (!(pModule = (NE_MODULE *)GlobalLock( pTask->hModule ))) return; + if (!(pModule = MODULE_GetPtr( pTask->hModule ))) return; if (firstTask) { diff --git a/memory/Makefile.in b/memory/Makefile.in index 357ded9be45..4287234615d 100644 --- a/memory/Makefile.in +++ b/memory/Makefile.in @@ -4,6 +4,7 @@ MODULE = memory C_SRCS = \ atom.c \ global.c \ + heap.c \ ldt.c \ local.c \ selector.c diff --git a/memory/global.c b/memory/global.c index 78e0081d97f..98d7bd05731 100644 --- a/memory/global.c +++ b/memory/global.c @@ -198,7 +198,9 @@ HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner, ptr = DDE_malloc(flags, size, &shmdata); else #endif /* CONFIG_IPC */ + { ptr = malloc( size ); + } if (!ptr) return 0; /* Allocate the selector(s) */ diff --git a/memory/heap.c b/memory/heap.c new file mode 100644 index 00000000000..945c84465e9 --- /dev/null +++ b/memory/heap.c @@ -0,0 +1,1091 @@ +/* + * Win32 heap functions + * + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include +#include "windows.h" +#include "debugger.h" +#include "kernel32.h" /* for CRITICAL_SECTION */ +#include "winbase.h" +#include "winerror.h" +#include "winnt.h" +#include "stddebug.h" +#include "debug.h" + +/* Note: the heap data structures are based on what Pietrek describes in his + * book 'Windows 95 System Programming Secrets'. The layout is not exactly + * the same, but could be easily adapted if it turns out some programs + * require it. + */ + +typedef struct tagARENA_INUSE +{ + DWORD size; /* Block size; must be the first field */ + WORD threadId; /* Allocating thread id */ + WORD magic; /* Magic number */ + DWORD callerEIP; /* EIP of caller upon allocation */ +} ARENA_INUSE; + +typedef struct tagARENA_FREE +{ + DWORD size; /* Block size; must be the first field */ + WORD threadId; /* Freeing thread id */ + WORD magic; /* Magic number */ + struct tagARENA_FREE *next; /* Next free arena */ + struct tagARENA_FREE *prev; /* Prev free arena */ +} ARENA_FREE; + +#define ARENA_FLAG_FREE 0x00000001 /* flags OR'ed with arena size */ +#define ARENA_FLAG_PREV_FREE 0x00000002 +#define ARENA_SIZE_MASK 0xfffffffc +#define ARENA_INUSE_MAGIC 0x4842 /* Value for arena 'magic' field */ +#define ARENA_FREE_MAGIC 0x4846 /* Value for arena 'magic' field */ + +#define ARENA_INUSE_FILLER 0x55 +#define ARENA_FREE_FILLER 0xaa + +#define HEAP_NB_FREE_LISTS 4 /* Number of free lists */ + +/* Max size of the blocks on the free lists */ +static const DWORD HEAP_freeListSizes[HEAP_NB_FREE_LISTS] = +{ + 0x20, 0x80, 0x200, 0xffffffff +}; + +typedef struct +{ + DWORD size; + ARENA_FREE arena; +} FREE_LIST_ENTRY; + +struct tagHEAP; + +typedef struct tagSUBHEAP +{ + DWORD size; /* Size of the whole sub-heap */ + DWORD commitSize; /* Committed size of the sub-heap */ + DWORD headerSize; /* Size of the heap header */ + struct tagSUBHEAP *next; /* Next sub-heap */ + struct tagHEAP *heap; /* Main heap structure */ + DWORD magic; /* Magic number */ +} SUBHEAP; + +#define SUBHEAP_MAGIC ((DWORD)('S' | ('U'<<8) | ('B'<<16) | ('H'<<24))) + +typedef struct tagHEAP +{ + SUBHEAP subheap; /* First sub-heap */ + struct tagHEAP *next; /* Next heap for this process */ + FREE_LIST_ENTRY freeList[HEAP_NB_FREE_LISTS]; /* Free lists */ + CRITICAL_SECTION critSection; /* Critical section for serialization */ + DWORD flags; /* Heap flags */ + DWORD magic; /* Magic number */ +} HEAP; + +#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24))) + +#define HEAP_DEF_SIZE 0x110000 /* Default heap size = 1Mb + 64Kb */ +#define HEAP_MIN_BLOCK_SIZE (8+sizeof(ARENA_FREE)) /* Min. heap block size */ + + +/*********************************************************************** + * HEAP_Dump + */ +void HEAP_Dump( HEAP *heap ) +{ + int i; + SUBHEAP *subheap; + char *ptr; + + printf( "Heap: %08lx\n", (DWORD)heap ); + printf( "Next: %08lx Sub-heaps: %08lx", + (DWORD)heap->next, (DWORD)&heap->subheap ); + subheap = &heap->subheap; + while (subheap->next) + { + printf( " -> %08lx", (DWORD)subheap->next ); + subheap = subheap->next; + } + + printf( "\nFree lists:\n Block Stat Size Id\n" ); + for (i = 0; i < HEAP_NB_FREE_LISTS; i++) + printf( "%08lx free %08lx %04x prev=%08lx next=%08lx\n", + (DWORD)&heap->freeList[i].arena, heap->freeList[i].arena.size, + heap->freeList[i].arena.threadId, + (DWORD)heap->freeList[i].arena.prev, + (DWORD)heap->freeList[i].arena.next ); + + subheap = &heap->subheap; + while (subheap) + { + DWORD freeSize = 0, usedSize = 0, arenaSize = subheap->headerSize; + printf( "\n\nSub-heap %08lx: size=%08lx committed=%08lx\n", + (DWORD)subheap, subheap->size, subheap->commitSize ); + + printf( "\n Block Stat Size Id\n" ); + ptr = (char*)subheap + subheap->headerSize; + while (ptr < (char *)subheap + subheap->size) + { + if (*(DWORD *)ptr & ARENA_FLAG_FREE) + { + ARENA_FREE *pArena = (ARENA_FREE *)ptr; + printf( "%08lx free %08lx %04x prev=%08lx next=%08lx\n", + (DWORD)pArena, pArena->size & ARENA_SIZE_MASK, + pArena->threadId, (DWORD)pArena->prev, + (DWORD)pArena->next); + ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); + arenaSize += sizeof(ARENA_FREE); + freeSize += pArena->size & ARENA_SIZE_MASK; + } + else if (*(DWORD *)ptr & ARENA_FLAG_PREV_FREE) + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr; + printf( "%08lx Used %08lx %04x back=%08lx EIP=%08lx\n", + (DWORD)pArena, pArena->size & ARENA_SIZE_MASK, + pArena->threadId, *((DWORD *)pArena - 1), + pArena->callerEIP ); + ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); + arenaSize += sizeof(ARENA_INUSE); + usedSize += pArena->size & ARENA_SIZE_MASK; + } + else + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr; + printf( "%08lx used %08lx %04x EIP=%08lx\n", + (DWORD)pArena, pArena->size & ARENA_SIZE_MASK, + pArena->threadId, pArena->callerEIP ); + ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); + arenaSize += sizeof(ARENA_INUSE); + usedSize += pArena->size & ARENA_SIZE_MASK; + } + } + printf( "\nTotal: Size=%08lx Committed=%08lx Free=%08lx Used=%08lx Arenas=%08lx (%ld%%)\n\n", + subheap->size, subheap->commitSize, freeSize, usedSize, + arenaSize, (arenaSize * 100) / subheap->size ); + subheap = subheap->next; + } +} + + +/*********************************************************************** + * HEAP_GetPtr + */ +static HEAP *HEAP_GetPtr( HANDLE32 heap ) +{ + HEAP *heapPtr = (HEAP *)heap; + if (!heapPtr || (heapPtr->magic != HEAP_MAGIC)) + { + fprintf( stderr, "Invalid heap %08lx!\n", heap ); + SetLastError( ERROR_INVALID_HANDLE ); + return NULL; + } + if (debugging_heap && !HeapValidate( heap, 0, NULL )) + { + HEAP_Dump( heapPtr ); + DEBUG_EnterDebugger(); + SetLastError( ERROR_INVALID_HANDLE ); + return NULL; + } + return heapPtr; +} + + +/*********************************************************************** + * HEAP_InsertFreeBlock + * + * Insert a free block into the free list. + */ +static void HEAP_InsertFreeBlock( HEAP *heap, ARENA_FREE *pArena ) +{ + FREE_LIST_ENTRY *pEntry = heap->freeList; + while (pEntry->size < pArena->size) pEntry++; + pArena->size |= ARENA_FLAG_FREE; + pArena->next = pEntry->arena.next; + pArena->next->prev = pArena; + pArena->prev = &pEntry->arena; + pEntry->arena.next = pArena; +} + + +/*********************************************************************** + * HEAP_FindSubHeap + * + * Find the sub-heap containing a given address. + */ +static SUBHEAP *HEAP_FindSubHeap( HEAP *heap, void *ptr ) +{ + SUBHEAP *sub = &heap->subheap; + while (sub) + { + if (((char *)ptr >= (char *)sub) && + ((char *)ptr < (char *)sub + sub->size)) return sub; + sub = sub->next; + } + return NULL; +} + + +/*********************************************************************** + * HEAP_Commit + * + * Make sure the heap storage is committed up to (not including) ptr. + */ +static BOOL HEAP_Commit( SUBHEAP *subheap, void *ptr ) +{ + DWORD size = (DWORD)((char *)ptr - (char *)subheap); + size = (size + 0xfff) & 0xfffff000; /* Align size on a page boundary */ + if (size > subheap->size) size = subheap->size; + if (size <= subheap->commitSize) return TRUE; + if (!VirtualAlloc( (char *)subheap + subheap->commitSize, + size - subheap->commitSize, MEM_COMMIT, + PAGE_EXECUTE_READWRITE)) + { + fprintf( stderr, "HEAP_Commit: could not commit %08lx bytes at %08lx for heap %08lx\n", + size - subheap->commitSize, + (DWORD)((char *)subheap + subheap->commitSize), + (DWORD)subheap->heap ); + return FALSE; + } + subheap->commitSize = size; + return TRUE; +} + + +/*********************************************************************** + * HEAP_Decommit + * + * If possible, decommit the heap storage from (including) 'ptr'. + */ +static BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr ) +{ + DWORD size = (DWORD)((char *)ptr - (char *)subheap); + size = (size + 0xfff) & 0xfffff000; /* Align size on a page boundary */ + if (size >= subheap->commitSize) return TRUE; + if (!VirtualFree( (char *)subheap + subheap->commitSize, + size - subheap->commitSize, MEM_DECOMMIT )) + { + fprintf( stderr, "HEAP_Decommit: could not decommit %08lx bytes at %08lx for heap %08lx\n", + size - subheap->commitSize, + (DWORD)((char *)subheap + subheap->commitSize), + (DWORD)subheap->heap ); + return FALSE; + } + subheap->commitSize = size; + return TRUE; +} + + +/*********************************************************************** + * HEAP_CreateFreeBlock + * + * Create a free block at a specified address. 'size' is the size of the + * whole block, including the new arena. + */ +static void HEAP_CreateFreeBlock( SUBHEAP *subheap, void *ptr, DWORD size ) +{ + ARENA_FREE *pFree; + + /* Create a free arena */ + + pFree = (ARENA_FREE *)ptr; + pFree->threadId = GetCurrentTask(); + pFree->magic = ARENA_FREE_MAGIC; + + /* If debugging, erase the freed block content */ + + if (debugging_heap) + { + char *pEnd = (char *)ptr + size; + if (pEnd > (char *)subheap + subheap->commitSize) + pEnd = (char *)subheap + subheap->commitSize; + if (pEnd > (char *)(pFree + 1)) + memset( pFree + 1, ARENA_FREE_FILLER, pEnd - (char *)(pFree + 1) ); + } + + /* Check if next block is free also */ + + if (((char *)ptr + size < (char *)subheap + subheap->size) && + (*(DWORD *)((char *)ptr + size) & ARENA_FLAG_FREE)) + { + /* Remove the next arena from the free list */ + ARENA_FREE *pNext = (ARENA_FREE *)((char *)ptr + size); + pNext->next->prev = pNext->prev; + pNext->prev->next = pNext->next; + size += (pNext->size & ARENA_SIZE_MASK) + sizeof(*pNext); + if (debugging_heap) + memset( pNext, ARENA_FREE_FILLER, sizeof(ARENA_FREE) ); + } + + /* Set the next block PREV_FREE flag and pointer */ + + if ((char *)ptr + size < (char *)subheap + subheap->size) + { + DWORD *pNext = (DWORD *)((char *)ptr + size); + *pNext |= ARENA_FLAG_PREV_FREE; + *(ARENA_FREE **)(pNext - 1) = pFree; + } + + /* Last, insert the new block into the free list */ + + pFree->size = size - sizeof(*pFree); + HEAP_InsertFreeBlock( subheap->heap, pFree ); +} + + +/*********************************************************************** + * HEAP_MakeInUseBlockFree + * + * Turn an in-use block into a free block. Can also decommit the end of + * the heap, and possibly even free the sub-heap altogether. + */ +static void HEAP_MakeInUseBlockFree( SUBHEAP *subheap, ARENA_INUSE *pArena ) +{ + ARENA_FREE *pFree; + DWORD size = (pArena->size & ARENA_SIZE_MASK) + sizeof(*pArena); + + /* Check if we can merge with previous block */ + + if (pArena->size & ARENA_FLAG_PREV_FREE) + { + pFree = *((ARENA_FREE **)pArena - 1); + size += (pFree->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE); + /* Remove it from the free list */ + pFree->next->prev = pFree->prev; + pFree->prev->next = pFree->next; + } + else pFree = (ARENA_FREE *)pArena; + + /* Create a free block */ + + HEAP_CreateFreeBlock( subheap, pFree, size ); + size = (pFree->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE); + if ((char *)pFree + size < (char *)subheap + subheap->size) + return; /* Not the last block, so nothing more to do */ + + /* Free the whole sub-heap if it's empty and not the original one */ + + if (((char *)pFree == (char *)subheap + subheap->headerSize) && + (subheap != &subheap->heap->subheap)) + { + /* FIXME: free the sub-heap here */ + return; + } + + /* Decommit the end of the heap */ + + HEAP_Decommit( subheap, pFree + 1 ); +} + + +/*********************************************************************** + * HEAP_ShrinkBlock + * + * Shrink an in-use block. + */ +static void HEAP_ShrinkBlock(SUBHEAP *subheap, ARENA_INUSE *pArena, DWORD size) +{ + if ((pArena->size & ARENA_SIZE_MASK) >= size + HEAP_MIN_BLOCK_SIZE) + { + HEAP_CreateFreeBlock( subheap, (char *)(pArena + 1) + size, + (pArena->size & ARENA_SIZE_MASK) - size ); + pArena->size = (pArena->size & ~ARENA_SIZE_MASK) | size; + } + else + { + /* Turn off PREV_FREE flag in next block */ + char *pNext = (char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK); + if (pNext < (char *)subheap + subheap->size) + *(DWORD *)pNext &= ~ARENA_FLAG_PREV_FREE; + } +} + + +/*********************************************************************** + * HEAP_CreateSubHeap + * + * Create a sub-heap of the given size. + */ +static SUBHEAP *HEAP_CreateSubHeap( DWORD commitSize, DWORD totalSize ) +{ + SUBHEAP *subheap; + + /* Round-up sizes on a 64K boundary */ + + totalSize = (totalSize + 0xffff) & 0xffff0000; + commitSize = (commitSize + 0xffff) & 0xffff0000; + if (!commitSize) commitSize = 0x10000; + if (totalSize < commitSize) totalSize = commitSize; + + /* Allocate the memory block */ + + if (!(subheap = VirtualAlloc( NULL, totalSize, + MEM_RESERVE, PAGE_EXECUTE_READWRITE ))) + { + fprintf( stderr, "HEAP_CreateSubHeap: could not VirtualAlloc %08lx bytes\n", + totalSize ); + return NULL; + } + if (!VirtualAlloc(subheap, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) + { + fprintf( stderr, "HEAP_CreateSubHeap: could not commit %08lx bytes for sub-heap %08lx\n", + commitSize, (DWORD)subheap ); + VirtualFree( subheap, 0, MEM_RELEASE ); + return NULL; + } + + /* Fill the sub-heap structure */ + + subheap->size = totalSize; + subheap->commitSize = commitSize; + subheap->headerSize = sizeof(*subheap); + subheap->next = NULL; + subheap->heap = NULL; + subheap->magic = SUBHEAP_MAGIC; + return subheap; +} + + +/*********************************************************************** + * HEAP_FindFreeBlock + * + * Find a free block at least as large as the requested size, and make sure + * the requested size is committed. + */ +static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, DWORD size, + SUBHEAP **ppSubHeap ) +{ + SUBHEAP *subheap; + ARENA_FREE *pArena; + FREE_LIST_ENTRY *pEntry = heap->freeList; + + /* Find a suitable free list, and in it find a block large enough */ + + while (pEntry->size < size) pEntry++; + pArena = pEntry->arena.next; + while (pArena != &heap->freeList[0].arena) + { + if (pArena->size > size) + { + subheap = HEAP_FindSubHeap( heap, pArena ); + if (!HEAP_Commit( subheap, (char *)pArena + sizeof(ARENA_INUSE) + + size + HEAP_MIN_BLOCK_SIZE)) + return NULL; + *ppSubHeap = subheap; + return pArena; + } + + pArena = pArena->next; + } + + /* If no block was found, attempt to grow the heap */ + + if (!(heap->flags & HEAP_GROWABLE)) + { + fprintf( stderr, "HEAP_FindFreeBlock: Not enough space in heap %08lx for %08lx bytes\n", + (DWORD)heap, size ); + return NULL; + } + size += sizeof(SUBHEAP) + sizeof(ARENA_FREE); + if (!(subheap = HEAP_CreateSubHeap( size, MAX( HEAP_DEF_SIZE, size ) ))) + return NULL; + + /* Insert the new sub-heap in the list */ + + subheap->heap = heap; + subheap->next = heap->subheap.next; + heap->subheap.next = subheap; + size = subheap->size; + dprintf_heap( stddeb, "HEAP_FindFreeBlock: created new sub-heap %08lx of %08lx bytes for heap %08lx\n", + (DWORD)subheap, size, (DWORD)heap ); + + HEAP_CreateFreeBlock( subheap, subheap + 1, size - sizeof(*subheap) ); + *ppSubHeap = subheap; + return (ARENA_FREE *)(subheap + 1); +} + + +/*********************************************************************** + * HEAP_IsValidArenaPtr + * + * Check that the pointer is inside the range possible for arenas. + */ +static BOOL HEAP_IsValidArenaPtr( HEAP *heap, void *ptr ) +{ + int i; + SUBHEAP *subheap = HEAP_FindSubHeap( heap, ptr ); + if (!subheap) return FALSE; + if ((char *)ptr >= (char *)subheap + subheap->headerSize) return TRUE; + if (subheap != &heap->subheap) return FALSE; + for (i = 0; i < HEAP_NB_FREE_LISTS; i++) + if (ptr == (void *)&heap->freeList[i].arena) return TRUE; + return FALSE; +} + + +/*********************************************************************** + * HEAP_ValidateFreeArena + */ +static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) +{ + char *heapEnd = (char *)subheap + subheap->size; + + /* Check magic number */ + if (pArena->magic != ARENA_FREE_MAGIC) + { + fprintf( stderr, "Heap %08lx: invalid free arena magic for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check size flags */ + if (!(pArena->size & ARENA_FLAG_FREE) || + (pArena->size & ARENA_FLAG_PREV_FREE)) + { + fprintf( stderr, "Heap %08lx: bad flags %lx for free arena %08lx\n", + (DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena ); + } + /* Check arena size */ + if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd) + { + fprintf( stderr, "Heap %08lx: bad size %08lx for free arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena ); + return FALSE; + } + /* Check that next pointer is valid */ + if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->next )) + { + fprintf( stderr, "Heap %08lx: bad next ptr %08lx for arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena ); + return FALSE; + } + /* Check that next arena is free */ + if (!(pArena->next->size & ARENA_FLAG_FREE) || + (pArena->next->magic != ARENA_FREE_MAGIC)) + { + fprintf( stderr, "Heap %08lx: next arena %08lx invalid for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena ); + return FALSE; + } + /* Check that prev pointer is valid */ + if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->prev )) + { + fprintf( stderr, "Heap %08lx: bad prev ptr %08lx for arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena ); + return FALSE; + } + /* Check that prev arena is free */ + if (!(pArena->prev->size & ARENA_FLAG_FREE) || + (pArena->prev->magic != ARENA_FREE_MAGIC)) + { + fprintf( stderr, "Heap %08lx: prev arena %08lx invalid for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena ); + return FALSE; + } + /* Check that next block has PREV_FREE flag */ + if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd) + { + if (!(*(DWORD *)((char *)(pArena + 1) + + (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE)) + { + fprintf( stderr, "Heap %08lx: free arena %08lx next block has no PREV_FREE flag\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check next block back pointer */ + if (*((ARENA_FREE **)((char *)(pArena + 1) + + (pArena->size & ARENA_SIZE_MASK)) - 1) != pArena) + { + fprintf( stderr, "Heap %08lx: arena %08lx has wrong back ptr %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena, + *((DWORD *)((char *)(pArena+1)+ (pArena->size & ARENA_SIZE_MASK)) - 1)); + return FALSE; + } + } + return TRUE; +} + + +/*********************************************************************** + * HEAP_ValidateInUseArena + */ +static BOOL HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena ) +{ + char *heapEnd = (char *)subheap + subheap->size; + + /* Check magic number */ + if (pArena->magic != ARENA_INUSE_MAGIC) + { + fprintf( stderr, "Heap %08lx: invalid in-use arena magic for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check size flags */ + if (pArena->size & ARENA_FLAG_FREE) + { + fprintf( stderr, "Heap %08lx: bad flags %lx for in-use arena %08lx\n", + (DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena ); + } + /* Check arena size */ + if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd) + { + fprintf( stderr, "Heap %08lx: bad size %08lx for in-use arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena ); + return FALSE; + } + /* Check next arena PREV_FREE flag */ + if (((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd) && + (*(DWORD *)((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE)) + { + fprintf( stderr, "Heap %08lx: in-use arena %08lx next block has PREV_FREE flag\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check prev free arena */ + if (pArena->size & ARENA_FLAG_PREV_FREE) + { + ARENA_FREE *pPrev = *((ARENA_FREE **)pArena - 1); + /* Check prev pointer */ + if (!HEAP_IsValidArenaPtr( subheap->heap, pPrev )) + { + fprintf(stderr, "Heap %08lx: bad back ptr %08lx for arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena ); + return FALSE; + } + /* Check that prev arena is free */ + if (!(pPrev->size & ARENA_FLAG_FREE) || + (pPrev->magic != ARENA_FREE_MAGIC)) + { + fprintf( stderr, "Heap %08lx: prev arena %08lx invalid for in-use %08lx\n", + (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena ); + return FALSE; + } + /* Check that prev arena is really the previous block */ + if ((char *)(pPrev + 1) + (pPrev->size & ARENA_SIZE_MASK) != (char *)pArena) + { + fprintf( stderr, "Heap %08lx: prev arena %08lx is not prev for in-use %08lx\n", + (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena ); + return FALSE; + } + } + return TRUE; +} + + +/*********************************************************************** + * HeapCreate (KERNEL32.336) + */ +HANDLE32 HeapCreate( DWORD flags, DWORD initialSize, DWORD maxSize ) +{ + int i; + HEAP *heap; + SUBHEAP *subheap; + FREE_LIST_ENTRY *pEntry; + + /* Allocate the heap block */ + + if (!maxSize) + { + maxSize = HEAP_DEF_SIZE; + flags |= HEAP_GROWABLE; + } + if (!(subheap = HEAP_CreateSubHeap( initialSize, maxSize ))) + { + SetLastError( ERROR_OUTOFMEMORY ); + return 0; + } + + /* Fill the heap structure */ + + heap = (HEAP *)subheap; + subheap->heap = heap; + subheap->headerSize = sizeof(HEAP); + heap->next = NULL; + heap->flags = flags; + heap->magic = HEAP_MAGIC; + InitializeCriticalSection( &heap->critSection ); + + /* Build the free lists */ + + for (i = 0, pEntry = heap->freeList; i < HEAP_NB_FREE_LISTS; i++, pEntry++) + { + pEntry->size = HEAP_freeListSizes[i]; + pEntry->arena.size = 0 | ARENA_FLAG_FREE; + pEntry->arena.next = i < HEAP_NB_FREE_LISTS-1 ? + &heap->freeList[i+1].arena : &heap->freeList[0].arena; + pEntry->arena.prev = i ? &heap->freeList[i-1].arena : + &heap->freeList[HEAP_NB_FREE_LISTS-1].arena; + pEntry->arena.threadId = 0; + pEntry->arena.magic = ARENA_FREE_MAGIC; + } + + /* Create the first free block */ + + HEAP_CreateFreeBlock( subheap, heap + 1, subheap->size - sizeof(*heap) ); + + /* We are done */ + + SetLastError( 0 ); + return (HANDLE32)heap; +} + + +/*********************************************************************** + * HeapDestroy (KERNEL32.337) + */ +BOOL HeapDestroy( HANDLE32 heap ) +{ + HEAP *heapPtr = HEAP_GetPtr( heap ); + SUBHEAP *subheap; + + dprintf_heap( stddeb, "HeapDestroy: %08lx\n", heap ); + if (!heapPtr) return FALSE; + + DeleteCriticalSection( &heapPtr->critSection ); + subheap = &heapPtr->subheap; + while (subheap) + { + SUBHEAP *next = subheap->next; + VirtualFree( subheap, subheap->commitSize, MEM_DECOMMIT ); + VirtualFree( subheap, 0, MEM_RELEASE ); + subheap = next; + } + return TRUE; +} + + +/*********************************************************************** + * HeapAlloc (KERNEL32.334) + */ +LPVOID HeapAlloc( HANDLE32 heap, DWORD flags, DWORD size ) +{ + ARENA_FREE *pArena; + ARENA_INUSE *pInUse; + SUBHEAP *subheap; + HEAP *heapPtr = HEAP_GetPtr( heap ); + + /* Validate the parameters */ + + if (!heapPtr) return NULL; + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap ); + size = (size + 3) & ~3; + if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE; + + /* Locate a suitable free block */ + + if (!(pArena = HEAP_FindFreeBlock( heapPtr, size, &subheap ))) + { + dprintf_heap( stddeb, "HeapAlloc(%08lx,%08lx,%08lx): returning NULL\n", + heap, flags, size ); + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + SetLastError( ERROR_OUTOFMEMORY ); + return NULL; + } + + /* Remove the arena from the free list */ + + pArena->next->prev = pArena->prev; + pArena->prev->next = pArena->next; + + /* Build the in-use arena */ + + pInUse = (ARENA_INUSE *)pArena; + pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE) + + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); + pInUse->callerEIP = *((DWORD *)&heap - 1); /* hack hack */ + pInUse->threadId = GetCurrentTask(); + pInUse->magic = ARENA_INUSE_MAGIC; + + /* Shrink the block */ + + HEAP_ShrinkBlock( subheap, pInUse, size ); + + if (flags & HEAP_ZERO_MEMORY) memset( pInUse + 1, 0, size ); + else if (debugging_heap) memset( pInUse + 1, ARENA_INUSE_FILLER, size ); + + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + SetLastError( 0 ); + + dprintf_heap( stddeb, "HeapAlloc(%08lx,%08lx,%08lx): returning %08lx\n", + heap, flags, size, (DWORD)(pInUse + 1) ); + return (LPVOID)(pInUse + 1); +} + + +/*********************************************************************** + * HeapFree (KERNEL32.338) + */ +BOOL HeapFree( HANDLE32 heap, DWORD flags, LPVOID ptr ) +{ + ARENA_INUSE *pInUse; + SUBHEAP *subheap; + HEAP *heapPtr = HEAP_GetPtr( heap ); + + /* Validate the parameters */ + + if (!heapPtr) return FALSE; + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap ); + if (!HeapValidate( heap, HEAP_NO_SERIALIZE, ptr )) + { + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + SetLastError( ERROR_INVALID_PARAMETER ); + dprintf_heap( stddeb, "HeapFree(%08lx,%08lx,%08lx): returning FALSE\n", + heap, flags, (DWORD)ptr ); + return FALSE; + } + + /* Turn the block into a free block */ + + pInUse = (ARENA_INUSE *)ptr - 1; + subheap = HEAP_FindSubHeap( heapPtr, pInUse ); + HEAP_MakeInUseBlockFree( subheap, pInUse ); + + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + SetLastError( 0 ); + + dprintf_heap( stddeb, "HeapFree(%08lx,%08lx,%08lx): returning TRUE\n", + heap, flags, (DWORD)ptr ); + return TRUE; +} + + +/*********************************************************************** + * HeapReAlloc (KERNEL32.340) + */ +LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size ) +{ + ARENA_INUSE *pArena; + DWORD oldSize; + HEAP *heapPtr; + SUBHEAP *subheap; + + if (!ptr) return HeapAlloc( heap, flags, size ); /* FIXME: correct? */ + if (!(heapPtr = HEAP_GetPtr( heap ))) return FALSE; + + /* Validate the parameters */ + + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | + HEAP_REALLOC_IN_PLACE_ONLY; + flags |= heapPtr->flags; + size = (size + 3) & ~3; + if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE; + + if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap ); + if (!HeapValidate( heap, HEAP_NO_SERIALIZE, ptr )) + { + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + SetLastError( ERROR_INVALID_PARAMETER ); + dprintf_heap( stddeb, "HeapReAlloc(%08lx,%08lx,%08lx,%08lx): returning NULL\n", + heap, flags, (DWORD)ptr, size ); + return NULL; + } + + /* Check if we need to grow the block */ + + pArena = (ARENA_INUSE *)ptr - 1; + pArena->threadId = GetCurrentTask(); + subheap = HEAP_FindSubHeap( heapPtr, pArena ); + oldSize = (pArena->size & ARENA_SIZE_MASK); + if (size > oldSize) + { + char *pNext = (char *)(pArena + 1) + oldSize; + if ((pNext < (char *)subheap + subheap->size) && + (*(DWORD *)pNext & ARENA_FLAG_FREE) && + (oldSize + (*(DWORD *)pNext & ARENA_SIZE_MASK) + sizeof(ARENA_FREE) >= size)) + { + /* The next block is free and large enough */ + ARENA_FREE *pFree = (ARENA_FREE *)pNext; + pFree->next->prev = pFree->prev; + pFree->prev->next = pFree->next; + pArena->size += (pFree->size & ARENA_SIZE_MASK) + sizeof(*pFree); + } + else /* Do it the hard way */ + { + ARENA_FREE *pNew; + ARENA_INUSE *pInUse; + SUBHEAP *newsubheap; + + if ((flags & HEAP_REALLOC_IN_PLACE_ONLY) || + !(pNew = HEAP_FindFreeBlock( heapPtr, size, &newsubheap ))) + { + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + return NULL; + } + + /* Build the in-use arena */ + + pNew->next->prev = pNew->prev; + pNew->prev->next = pNew->next; + pInUse = (ARENA_INUSE *)pNew; + pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE) + + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); + pInUse->threadId = GetCurrentTask(); + pInUse->magic = ARENA_INUSE_MAGIC; + memcpy( pInUse + 1, pArena + 1, oldSize ); + + /* Free the previous block */ + + HEAP_MakeInUseBlockFree( subheap, pArena ); + subheap = newsubheap; + pArena = pInUse; + } + } + + + /* Shrink the block */ + + HEAP_ShrinkBlock( subheap, pArena, size ); + + /* Clear the extra bytes if needed */ + + if (size > oldSize) + { + if (flags & HEAP_ZERO_MEMORY) + memset( (char *)(pArena + 1) + oldSize, 0, + (pArena->size & ARENA_SIZE_MASK) - oldSize ); + else if (debugging_heap) + memset( (char *)(pArena + 1) + oldSize, ARENA_INUSE_FILLER, + (pArena->size & ARENA_SIZE_MASK) - oldSize ); + } + + /* Return the new arena */ + + pArena->callerEIP = *((DWORD *)&heap - 1); /* hack hack */ + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + + dprintf_heap( stddeb, "HeapReAlloc(%08lx,%08lx,%08lx,%08lx): returning %08lx\n", + heap, flags, (DWORD)ptr, size, (DWORD)(pArena + 1) ); + return (LPVOID)(pArena + 1); +} + + +/*********************************************************************** + * HeapCompact (KERNEL32.335) + */ +DWORD HeapCompact( HANDLE32 heap, DWORD flags ) +{ + return 0; +} + + +/*********************************************************************** + * HeapLock (KERNEL32.339) + */ +BOOL HeapLock( HANDLE32 heap ) +{ + HEAP *heapPtr = HEAP_GetPtr( heap ); + + if (!heapPtr) return FALSE; + EnterCriticalSection( &heapPtr->critSection ); + return TRUE; +} + + +/*********************************************************************** + * HeapUnlock (KERNEL32.342) + */ +BOOL HeapUnlock( HANDLE32 heap ) +{ + HEAP *heapPtr = HEAP_GetPtr( heap ); + + if (!heapPtr) return FALSE; + LeaveCriticalSection( &heapPtr->critSection ); + return TRUE; +} + + +/*********************************************************************** + * HeapSize (KERNEL32.341) + */ +DWORD HeapSize( HANDLE32 heap, DWORD flags, LPVOID ptr ) +{ + DWORD ret; + HEAP *heapPtr = HEAP_GetPtr( heap ); + + if (!heapPtr) return FALSE; + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap ); + if (!HeapValidate( heap, HEAP_NO_SERIALIZE, ptr )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + ret = 0xffffffff; + } + else + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr - 1; + ret = pArena->size & ARENA_SIZE_MASK; + } + if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap ); + + dprintf_heap( stddeb, "HeapSize(%08lx,%08lx,%08lx): returning %08lx\n", + heap, flags, (DWORD)ptr, ret ); + return ret; +} + + +/*********************************************************************** + * HeapValidate (KERNEL32.343) + */ +BOOL HeapValidate( HANDLE32 heap, DWORD flags, LPVOID block ) +{ + SUBHEAP *subheap; + HEAP *heapPtr = (HEAP *)heap; + + if (!heapPtr || (heapPtr->magic != HEAP_MAGIC)) + { + fprintf( stderr, "Invalid heap %08lx!\n", heap ); + return FALSE; + } + + if (block) + { + if (!(subheap = HEAP_FindSubHeap( heapPtr, block )) || + ((char *)block < (char *)subheap + subheap->headerSize + + sizeof(ARENA_INUSE))) + { + fprintf( stderr, "Heap %08lx: block %08lx is not inside heap\n", + (DWORD)heap, (DWORD)block ); + return FALSE; + } + return HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1 ); + } + + subheap = &heapPtr->subheap; + while (subheap) + { + char *ptr = (char *)subheap + subheap->headerSize; + while (ptr < (char *)subheap + subheap->size) + { + if (*(DWORD *)ptr & ARENA_FLAG_FREE) + { + if (!HEAP_ValidateFreeArena( subheap, (ARENA_FREE *)ptr )) + return FALSE; + ptr += sizeof(ARENA_FREE) + (*(DWORD *)ptr & ARENA_SIZE_MASK); + } + else + { + if (!HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)ptr )) + return FALSE; + ptr += sizeof(ARENA_INUSE) + (*(DWORD *)ptr & ARENA_SIZE_MASK); + } + } + subheap = subheap->next; + } + return TRUE; +} + + +/*********************************************************************** + * HeapWalk (KERNEL32.344) + */ +BOOL HeapWalk( HANDLE32 heap, void *entry ) +{ + return FALSE; +} diff --git a/memory/local.c b/memory/local.c index f249a8016a1..96fa99903b8 100644 --- a/memory/local.c +++ b/memory/local.c @@ -313,7 +313,7 @@ BOOL LocalInit( HANDLE selector, WORD start, WORD end ) if (start == 0) { /* Check if the segment is the DGROUP of a module */ - if ((pModule = (NE_MODULE *)GlobalLock( GetExePtr( selector ) ))) + if ((pModule = MODULE_GetPtr( GetExePtr( selector ) ))) { SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1; if (pModule->dgroup && (pSeg->selector == selector)) { diff --git a/memory/selector.c b/memory/selector.c index 26afe791b80..b3b117f2a90 100644 --- a/memory/selector.c +++ b/memory/selector.c @@ -121,9 +121,9 @@ static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, { LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry ); entry.base += 0x10000; - size -= 0x10000; - entry.limit = (size > 0x10000) ? 0xffff : size-1; - entry.limit_in_pages = 0; + /* Apparently the next selectors should *not* get a 64k limit. */ + /* Can't remember where I read they should... --AJ */ + entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000; } } diff --git a/misc/commdlg.c b/misc/commdlg.c index 66beced5763..089019b2cd1 100644 --- a/misc/commdlg.c +++ b/misc/commdlg.c @@ -2,6 +2,7 @@ * COMMDLG functions * * Copyright 1994 Martin Ayotte + * Copyright 1996 Albrecht Kleine */ #include @@ -693,33 +694,6 @@ BOOL ChooseColor(LPCHOOSECOLOR lpChCol) } -/*********************************************************************** - * ColorDlgProc (COMMDLG.8) - */ -LRESULT ColorDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) -{ - switch (wMsg) - { - case WM_INITDIALOG: - dprintf_commdlg(stddeb,"ColorDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam); - ShowWindow(hWnd, SW_SHOWNORMAL); - return (TRUE); - case WM_COMMAND: - switch (wParam) - { - case IDOK: - EndDialog(hWnd, TRUE); - return(TRUE); - case IDCANCEL: - EndDialog(hWnd, FALSE); - return(TRUE); - } - return(FALSE); - } - return FALSE; -} - - /*********************************************************************** * FindTextDlg (COMMDLG.11) */ @@ -1119,3 +1093,1068 @@ short GetFileTitle(LPCSTR lpFile, LPSTR lpTitle, UINT cbBuf) strncpy(lpTitle, &lpFile[i], len); return 0; } + + +/* --------------------------- Choose Color Dialog ------------------------------ */ + +static const COLORREF predefcolors[6][8]= +{ + { 0x008080FFL, 0x0080FFFFL, 0x0080FF80L, 0x0080FF00L, + 0x00FFFF80L, 0x00FF8000L, 0x00C080FFL, 0x00FF80FFL }, + { 0x000000FFL, 0x0000FFFFL, 0x0000FF80L, 0x0040FF00L, + 0x00FFFF00L, 0x00C08000L, 0x00C08080L, 0x00FF00FFL }, + + { 0x00404080L, 0x004080FFL, 0x0000FF00L, 0x00808000L, + 0x00804000L, 0x00FF8080L, 0x00400080L, 0x008000FFL }, + { 0x00000080L, 0x000080FFL, 0x00008000L, 0x00408000L, + 0x00FF0000L, 0x00A00000L, 0x00800080L, 0x00FF0080L }, + + { 0x00000040L, 0x00004080L, 0x00004000L, 0x00404000L, + 0x00800000L, 0x00400000L, 0x00400040L, 0x00800040L }, + { 0x00000000L, 0x00008080L, 0x00408080L, 0x00808080L, + 0x00808040L, 0x00C0C0C0L, 0x00400040L, 0x00FFFFFFL }, +}; + +struct CCPRIVATE +{ + LPCHOOSECOLOR lpcc; /* points to public known data structure */ + int nextuserdef; /* next free place in user defined color array */ + HDC hdcMem; /* color graph used for BitBlt() */ + RECT fullsize; /* original dialog window size */ + UINT msetrgb; /* # of SETRGBSTRING message (today not used) */ + RECT old3angle; /* last position of l-marker */ + RECT oldcross; /* last position of color/satuation marker */ + int h; + int s; + int l; /* for temporary storing of hue,sat,lum */ +}; + +/*********************************************************************** + * CC_HSLtoRGB [internal] + */ +static int CC_HSLtoRGB(char c,int hue,int sat,int lum) +{ + int res=0,maxrgb; + + /* hue */ + switch(c) + { + case 'R':if (hue>80) hue-=80; else hue+=160; break; + case 'G':if (hue>160) hue-=160; else hue+=80; break; + case 'B':break; + } + + /* l below 120 */ + maxrgb=(256*MIN(120,lum))/120; /* 0 .. 256 */ + if (hue< 80) + res=0; + else + if (hue< 120) + { + res=(hue-80)* maxrgb; /* 0...10240 */ + res/=40; /* 0...256 */ + } + else + if (hue< 200) + res=maxrgb; + else + { + res=(240-hue)* maxrgb; + res/=40; + } + res=res-maxrgb/2; /* -128...128 */ + + /* saturation */ + res=maxrgb/2 + (sat*res) /240; /* 0..256 */ + + /* lum above 120 */ + if (lum>120 && res<256) + res+=((lum-120) * (256-res))/120; + + return MIN(res,255); +} + +/*********************************************************************** + * CC_RGBtoHSL [internal] + */ +static int CC_RGBtoHSL(char c,int r,int g,int b) +{ + WORD maxi,mini,mmsum,mmdif,result=0; + int iresult=0; + + maxi=MAX(r,b); + maxi=MAX(maxi,g); + mini=MIN(r,b); + mini=MIN(mini,g); + + mmsum=maxi+mini; + mmdif=maxi-mini; + + switch(c) + { + /* lum */ + case 'L':mmsum*=120; /* 0...61200=(255+255)*120 */ + result=mmsum/255; /* 0...240 */ + break; + /* saturation */ + case 'S':if (!mmsum) + result=0; + else + if (!mini || maxi==255) + result=240; + else + { + result=mmdif*240; /* 0...61200=255*240 */ + result/= (mmsum>255 ? mmsum=510-mmsum : mmsum); /* 0..255 */ + } + break; + /* hue */ + case 'H':if (!mmdif) + result=160; + else + { + if (maxi==r) + { + iresult=40*(g-b); /* -10200 ... 10200 */ + iresult/=(int)mmdif; /* -40 .. 40 */ + if (iresult<0) + iresult+=240; /* 0..40 and 200..240 */ + } + else + if (maxi==g) + { + iresult=40*(b-r); + iresult/=(int)mmdif; + iresult+=80; /* 40 .. 120 */ + } + else + if (maxi==b) + { + iresult=40*(r-g); + iresult/=(int)mmdif; + iresult+=160; /* 120 .. 200 */ + } + result=iresult; + } + break; + } + return result; /* is this integer arithmetic precise enough ? */ +} + +#define DISTANCE 4 + +/*********************************************************************** + * CC_MouseCheckPredefColorArray [internal] + */ +static int CC_MouseCheckPredefColorArray(HWND hDlg,int dlgitem,int rows,int cols, + LPARAM lParam,COLORREF *cr) +{ + HWND hwnd; + POINT point; + RECT rect; + int dx,dy,x,y; + + point.x=LOWORD(lParam); + point.y=HIWORD(lParam); + ClientToScreen(hDlg,&point); + + hwnd=GetDlgItem(hDlg,dlgitem); + GetWindowRect(hwnd,&rect); + if (PtInRect(&rect,point)) + { + dx=(rect.right-rect.left)/cols; + dy=(rect.bottom-rect.top)/rows; + ScreenToClient(hwnd,&point); + + if (point.x % dx < (dx-DISTANCE) && point.y % dy < (dy-DISTANCE)) + { + x=point.x/dx; + y=point.y/dy; + *cr=predefcolors[y][x]; + /* FIXME: Draw_a_Focus_Rect() */ + return 1; + } + } + return 0; +} + +/*********************************************************************** + * CC_MouseCheckUserColorArray [internal] + */ +static int CC_MouseCheckUserColorArray(HWND hDlg,int dlgitem,int rows,int cols, + LPARAM lParam,COLORREF *cr,COLORREF*crarr) +{ + HWND hwnd; + POINT point; + RECT rect; + int dx,dy,x,y; + + point.x=LOWORD(lParam); + point.y=HIWORD(lParam); + ClientToScreen(hDlg,&point); + + hwnd=GetDlgItem(hDlg,dlgitem); + GetWindowRect(hwnd,&rect); + if (PtInRect(&rect,point)) + { + dx=(rect.right-rect.left)/cols; + dy=(rect.bottom-rect.top)/rows; + ScreenToClient(hwnd,&point); + + if (point.x % dx < (dx-DISTANCE) && point.y % dy < (dy-DISTANCE)) + { + x=point.x/dx; + y=point.y/dy; + *cr=crarr[x+cols*y]; + /* FIXME: Draw_a_Focus_Rect() */ + return 1; + } + } + return 0; +} + +#define MAXVERT 240 +#define MAXHORI 239 + +/* 240 ^...... ^^ 240 + | . || + SAT | . || LUM + | . || + +-----> 239 ---- + HUE +*/ +/*********************************************************************** + * CC_MouseCheckColorGraph [internal] + */ +static int CC_MouseCheckColorGraph(HWND hDlg,int dlgitem,int *hori,int *vert,LPARAM lParam) +{ + HWND hwnd; + POINT point; + RECT rect; + long x,y; + + point.x=LOWORD(lParam); + point.y=HIWORD(lParam); + ClientToScreen(hDlg,&point); + hwnd=GetDlgItem(hDlg,dlgitem); + GetWindowRect(hwnd,&rect); + if (PtInRect(&rect,point)) + { + GetClientRect(hwnd,&rect); + ScreenToClient(hwnd,&point); + + x=(long)point.x*MAXHORI; + x/=rect.right; + y=(long)(rect.bottom-point.y)*MAXVERT; + y/=rect.bottom; + + if (hori) + *hori=x; + if (vert) + *vert=y; + return 1; + } + else + return 0; +} +/*********************************************************************** + * CC_MouseCheckResultWindow [internal] + */ +static int CC_MouseCheckResultWindow(HWND hDlg,LPARAM lParam) +{ + HWND hwnd; + POINT point; + RECT rect; + point.x=LOWORD(lParam); + point.y=HIWORD(lParam); + ClientToScreen(hDlg,&point); + hwnd=GetDlgItem(hDlg,0x2c5); + GetWindowRect(hwnd,&rect); + if (PtInRect(&rect,point)) + { + PostMessage(hDlg,WM_COMMAND,0x2c9,0); + return 1; + } + return 0; +} + +/*********************************************************************** + * CC_CheckDigitsInEdit [internal] + */ +static int CC_CheckDigitsInEdit(HWND hwnd,int maxval) +{ + int i,k,m,result,value; + long editpos; + char buffer[30]; + GetWindowText(hwnd,buffer,30-1); + m=lstrlen(buffer); + result=0; + + for (i=0;i'9') + { + for (k=i+1;k<=m;k++) /* delete bad character */ + { + buffer[i]=buffer[k]; + m--; + } + buffer[m]=0; + result=1; + } + + value=atoi(buffer); + if (value>maxval) /* build a new string */ + { + sprintf(buffer,"%d",maxval); + result=2; + } + if (result) + { + editpos=SendMessage(hwnd,EM_GETSEL,0,0); + SetWindowText(hwnd,buffer); + SendMessage(hwnd,EM_SETSEL,0,editpos); + } + return value; +} + + + +/*********************************************************************** + * CC_PaintSelectedColor [internal] + */ +static void CC_PaintSelectedColor(HWND hDlg,COLORREF cr) +{ + RECT rect; + HDC hdc; + HBRUSH hBrush; + HWND hwnd=GetDlgItem(hDlg,0x2c5); + if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */ + { + hdc=GetDC(hwnd); + GetClientRect (hwnd, &rect) ; + hBrush = CreateSolidBrush(cr); + if (hBrush) + { + hBrush = SelectObject (hdc, hBrush) ; + Rectangle (hdc, rect.left,rect.top,rect.right/2,rect.bottom); + DeleteObject (SelectObject (hdc,hBrush)) ; + hBrush=CreateSolidBrush(GetNearestColor(hdc,cr)); + if (hBrush) + { + hBrush= SelectObject (hdc, hBrush) ; + Rectangle (hdc, rect.right/2-1,rect.top,rect.right,rect.bottom); + DeleteObject (SelectObject (hdc, hBrush)) ; + } + } + ReleaseDC(hwnd,hdc); + } +} + +/*********************************************************************** + * CC_PaintTriangle [internal] + */ +static void CC_PaintTriangle(HWND hDlg,int y) +{ + HDC hDC; + long temp; + int w=GetDialogBaseUnits(); + POINT points[3]; + int height; + int oben; + RECT rect; + HWND hwnd=GetDlgItem(hDlg,0x2be); + struct CCPRIVATE *lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + + if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */ + { + GetClientRect(hwnd,&rect); + height=rect.bottom; + hDC=GetDC(hDlg); + + points[0].y=rect.top; + points[0].x=rect.right; /* | /| */ + ClientToScreen(hwnd,points); /* | / | */ + ScreenToClient(hDlg,points); /* |< | */ + oben=points[0].y; /* | \ | */ + /* | \| */ + temp=(long)height*(long)y; + points[0].y=oben+height -temp/(long)MAXVERT; + points[1].y=points[0].y+w; + points[2].y=points[0].y-w; + points[2].x=points[1].x=points[0].x + w; + + if (lpp->old3angle.left) + FillRect(hDC,&lpp->old3angle,GetStockObject(WHITE_BRUSH)); + lpp->old3angle.left =points[0].x; + lpp->old3angle.right =points[1].x+1; + lpp->old3angle.top =points[2].y-1; + lpp->old3angle.bottom=points[1].y+1; + Polygon(hDC,points,3); + ReleaseDC(hDlg,hDC); + } +} + + +/*********************************************************************** + * CC_PaintCross [internal] + */ +static void CC_PaintCross(HWND hDlg,int x,int y) +{ + HDC hDC; + long temp; + int w=GetDialogBaseUnits(); + HWND hwnd=GetDlgItem(hDlg,0x2c6); + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + RECT rect; + POINT point; + HPEN hPen; + + if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */ + { + GetClientRect(hwnd,&rect); + + hDC=GetDC(hwnd); + hPen=CreatePen(PS_SOLID,2,0); + hPen=SelectObject(hDC,hPen); + + temp=(long)rect.right*(long)x; + point.x=temp/(long)MAXHORI; + temp=(long)rect.bottom*(long)y; + point.y=rect.bottom-temp/(long)MAXVERT; + + if (lpp->oldcross.left!=lpp->oldcross.right) + BitBlt(hDC,lpp->oldcross.left,lpp->oldcross.top, + lpp->oldcross.right-lpp->oldcross.left, + lpp->oldcross.bottom-lpp->oldcross.top, + lpp->hdcMem,lpp->oldcross.left,lpp->oldcross.top,SRCCOPY); + + lpp->oldcross.left =point.x-w-1; + lpp->oldcross.right =point.x+w+1; + lpp->oldcross.top =point.y-w-1; + lpp->oldcross.bottom=point.y+w+1; + + if (point.y+w/23) + { + MoveTo(hDC,point.x,point.y-w/2); + LineTo(hDC,point.x,MAX(2,point.y-w )); + } + if (point.x+w/23) + { + MoveTo(hDC,point.x-w/2,point.y); + LineTo(hDC,MAX(2,point.x-w), point.y); + } + + DeleteObject(SelectObject(hDC,hPen)); + ReleaseDC(hwnd,hDC); + } +} + + +#define XSTEPS 36 +#define YSTEPS 48 + + +/*********************************************************************** + * CC_PrepareColorGraph [internal] + */ +static void CC_PrepareColorGraph(HWND hDlg) +{ + int sdif,hdif,xdif,ydif,r,g,b,hue,sat; + HWND hwnd=GetDlgItem(hDlg,0x2c6); + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + HBRUSH hbrush; + HDC hdc ; + RECT rect,client; + HBITMAP hbmMem; + HCURSOR hcursor=SetCursor(LoadCursor(0,IDC_WAIT)); + + GetClientRect(hwnd,&client); + hdc=GetDC(hwnd); + lpp->hdcMem = CreateCompatibleDC(hdc); + hbmMem = CreateCompatibleBitmap(hdc,client.right,client.bottom); + SelectObject(lpp->hdcMem,hbmMem); + + xdif=client.right /XSTEPS; + ydif=client.bottom/YSTEPS+1; + hdif=239/XSTEPS; + sdif=240/YSTEPS; + for(rect.left=hue=0;hue<239+hdif;hue+=hdif) + { + rect.right=rect.left+xdif; + rect.bottom=client.bottom; + for(sat=0;sat<240+sdif;sat+=sdif) + { + rect.top=rect.bottom-ydif; + r=CC_HSLtoRGB('R',hue,sat,120); + g=CC_HSLtoRGB('G',hue,sat,120); + b=CC_HSLtoRGB('B',hue,sat,120); + hbrush=CreateSolidBrush(RGB(r,g,b)); + FillRect(lpp->hdcMem,&rect,hbrush); + DeleteObject(hbrush); + rect.bottom=rect.top; + } + rect.left=rect.right; + } + ReleaseDC(hwnd,hdc); + SetCursor(hcursor); + /* FIXME perhaps we should do it only ONCE for all, like hCDRom,.... ? */ +} + +/*********************************************************************** + * CC_PaintColorGraph [internal] + */ +static void CC_PaintColorGraph(HWND hDlg) +{ + HWND hwnd=GetDlgItem(hDlg,0x2c6); + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + HDC hDC; + RECT rect; + if (IsWindowVisible(hwnd)) /* if full size */ + { + if (!lpp->hdcMem) + CC_PrepareColorGraph(hDlg); /* should not be necessary */ + + hDC=GetDC(hwnd); + GetClientRect(hwnd,&rect); + if (lpp->hdcMem) + BitBlt(hDC,0,0,rect.right,rect.bottom,lpp->hdcMem,0,0,SRCCOPY); + else + fprintf(stderr,"choose color: hdcMem is not defined\n"); + ReleaseDC(hwnd,hDC); + } +} +/*********************************************************************** + * CC_PaintLumBar [internal] + */ +static void CC_PaintLumBar(HWND hDlg,int hue,int sat) +{ + HWND hwnd=GetDlgItem(hDlg,0x2be); + RECT rect,client; + int lum,ldif,ydif,r,g,b; + HBRUSH hbrush; + HDC hDC; + + if (IsWindowVisible(hwnd)) + { + hDC=GetDC(hwnd); + GetClientRect(hwnd,&client); + rect=client; + + ldif=240/YSTEPS; + ydif=client.bottom/YSTEPS+1; + for(lum=0;lum<240+ldif;lum+=ldif) + { + rect.top=MAX(0,rect.bottom-ydif); + r=CC_HSLtoRGB('R',hue,sat,lum); + g=CC_HSLtoRGB('G',hue,sat,lum); + b=CC_HSLtoRGB('B',hue,sat,lum); + hbrush=CreateSolidBrush(RGB(r,g,b)); + FillRect(hDC,&rect,hbrush); + DeleteObject(hbrush); + rect.bottom=rect.top; + } + GetClientRect(hwnd,&rect); + FrameRect(hDC,&rect,GetStockObject(BLACK_BRUSH)); + ReleaseDC(hwnd,hDC); + } +} + +/*********************************************************************** + * CC_EditSetRGB [internal] + */ +static void CC_EditSetRGB(HWND hDlg,COLORREF cr) +{ + char buffer[10]; + int r=GetRValue(cr); + int g=GetGValue(cr); + int b=GetBValue(cr); + if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */ + { + sprintf(buffer,"%d",r); + SetWindowText(GetDlgItem(hDlg,0x2c2),buffer); + sprintf(buffer,"%d",g); + SetWindowText(GetDlgItem(hDlg,0x2c3),buffer); + sprintf(buffer,"%d",b); + SetWindowText(GetDlgItem(hDlg,0x2c4),buffer); + } +} + +/*********************************************************************** + * CC_EditSetHSL [internal] + */ +static void CC_EditSetHSL(HWND hDlg,int h,int s,int l) +{ + char buffer[10]; + if (IsWindowVisible(GetDlgItem(hDlg,0x2c6))) /* if full size */ + { + sprintf(buffer,"%d",h); + SetWindowText(GetDlgItem(hDlg,0x2bf),buffer); + sprintf(buffer,"%d",s); + SetWindowText(GetDlgItem(hDlg,0x2c0),buffer); + sprintf(buffer,"%d",l); + SetWindowText(GetDlgItem(hDlg,0x2c1),buffer); + } + CC_PaintLumBar(hDlg,h,s); +} + +/*********************************************************************** + * CC_SwitchToFullSize [internal] + */ +static void CC_SwitchToFullSize(HWND hDlg,COLORREF result,LPRECT lprect) +{ + int i; + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + + EnableWindow(GetDlgItem(hDlg,0x2cf),FALSE); + CC_PrepareColorGraph(hDlg); + for (i=0x2bf;i<0x2c5;i++) + EnableWindow(GetDlgItem(hDlg,i),TRUE); + for (i=0x2d3;i<0x2d9;i++) + EnableWindow(GetDlgItem(hDlg,i),TRUE); + EnableWindow(GetDlgItem(hDlg,0x2c9),TRUE); + EnableWindow(GetDlgItem(hDlg,0x2c8),TRUE); + + if (lprect) + SetWindowPos(hDlg,NULL,0,0,lprect->right-lprect->left, + lprect->bottom-lprect->top, SWP_NOMOVE|SWP_NOZORDER); + + ShowWindow(GetDlgItem(hDlg,0x2c6),SW_SHOW); + ShowWindow(GetDlgItem(hDlg,0x2be),SW_SHOW); + ShowWindow(GetDlgItem(hDlg,0x2c5),SW_SHOW); + + CC_EditSetRGB(hDlg,result); + CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l); +} + +/*********************************************************************** + * CC_PaintPredefColorArray [internal] + */ +static void CC_PaintPredefColorArray(HWND hDlg,int rows,int cols) +{ + HWND hwnd=GetDlgItem(hDlg,0x2d0); + RECT rect; + HDC hdc; + HBRUSH hBrush; + int dx,dy,i,j,k; + + GetClientRect(hwnd,&rect); + dx=rect.right/cols; + dy=rect.bottom/rows; + k=rect.left; + + hdc=GetDC(hwnd); + GetClientRect (hwnd, &rect) ; + + for (j=0;jFlags & CC_ENABLEHOOK) + if (lpcc->lpfnHook) + return TRUE; + return FALSE; +} + +/*********************************************************************** + * CC_WMInitDialog [internal] + */ +static LONG CC_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + int i,res; + HWND hwnd; + RECT rect; + POINT point; + struct CCPRIVATE * lpp; + + dprintf_commdlg(stddeb,"ColorDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam); + lpp=calloc(1,sizeof(struct CCPRIVATE)); + lpp->lpcc=(LPCHOOSECOLOR)lParam; + if (lpp->lpcc->lStructSize != sizeof(CHOOSECOLOR)) + { + EndDialog (hDlg, 0) ; + return FALSE; + } + SetWindowLong(hDlg, DWL_USER, (LONG)lpp); + + if (!(lpp->lpcc->Flags & CC_SHOWHELP)) + ShowWindow(GetDlgItem(hDlg,0x40e),SW_HIDE); + lpp->msetrgb=RegisterWindowMessage(MAKE_SEGPTR(SETRGBSTRING)); +#if 0 + cpos=MAKELONG(5,7); /* init */ + if (lpp->lpcc->Flags & CC_RGBINIT) + { + for (i=0;i<6;i++) + for (j=0;j<8;j++) + if (predefcolors[i][j]==lpp->lpcc->rgbResult) + { + cpos=MAKELONG(i,j); + goto found; + } + } + found: + /* FIXME: Draw_a_focus_rect & set_init_values */ +#endif + GetWindowRect(hDlg,&lpp->fullsize); + if (lpp->lpcc->Flags & CC_FULLOPEN || lpp->lpcc->Flags & CC_PREVENTFULLOPEN) + { + hwnd=GetDlgItem(hDlg,0x2cf); + EnableWindow(hwnd,FALSE); + } + if (!(lpp->lpcc->Flags & CC_FULLOPEN) || lpp->lpcc->Flags & CC_PREVENTFULLOPEN) + { + rect=lpp->fullsize; + res=rect.bottom-rect.top; + hwnd=GetDlgItem(hDlg,0x2c6); /* cut at left border */ + point.x=point.y=0; + ClientToScreen(hwnd,&point); + ScreenToClient(hDlg,&point); + GetClientRect(hDlg,&rect); + point.x+=GetSystemMetrics(SM_CXDLGFRAME); + SetWindowPos(hDlg,NULL,0,0,point.x,res,SWP_NOMOVE|SWP_NOZORDER); + + ShowWindow(GetDlgItem(hDlg,0x2c6),SW_HIDE); + ShowWindow(GetDlgItem(hDlg,0x2c5),SW_HIDE); + } + else + CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,NULL); + res=TRUE; + for (i=0x2bf;i<0x2c5;i++) + SendMessage(GetDlgItem(hDlg,i),EM_LIMITTEXT,3,0); /* max 3 digits: xyz */ + if (CC_HookCallChk(lpp->lpcc)) + res=CallWindowProc((FARPROC)lpp->lpcc->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam); + return res; +} + +/*********************************************************************** + * CC_WMCommand [internal] + */ +static LRESULT CC_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + int r,g,b,i,xx; + UINT cokmsg; + HDC hdc; + COLORREF *cr; + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + switch (wParam) + { + case 0x2c2: /* edit notify RGB */ + case 0x2c3: + case 0x2c4: + if (HIWORD(lParam)==EN_UPDATE) + { + i=CC_CheckDigitsInEdit(LOWORD(lParam),255); + r=GetRValue(lpp->lpcc->rgbResult); + g=GetGValue(lpp->lpcc->rgbResult); + b=GetBValue(lpp->lpcc->rgbResult); + xx=0; + switch (wParam) + { + case 0x2c2:if ((xx=(i!=r))) r=i;break; + case 0x2c3:if ((xx=(i!=g))) g=i;break; + case 0x2c4:if ((xx=(i!=b))) b=i;break; + } + if (xx) /* something has changed */ + { + lpp->lpcc->rgbResult=RGB(r,g,b); + CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult); + lpp->h=CC_RGBtoHSL('H',r,g,b); + lpp->s=CC_RGBtoHSL('S',r,g,b); + lpp->l=CC_RGBtoHSL('L',r,g,b); + CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l); + CC_PaintCross(hDlg,lpp->h,lpp->s); + CC_PaintTriangle(hDlg,lpp->l); + } + } + break; + + case 0x2bf: /* edit notify HSL */ + case 0x2c0: + case 0x2c1: + if (HIWORD(lParam)==EN_UPDATE) + { + i=CC_CheckDigitsInEdit(LOWORD(lParam),wParam==0x2bf?239:240); + xx=0; + switch (wParam) + { + case 0x2bf:if ((xx=(i!=lpp->h))) lpp->h=i;break; + case 0x2c0:if ((xx=(i!=lpp->s))) lpp->s=i;break; + case 0x2c1:if ((xx=(i!=lpp->l))) lpp->l=i;break; + } + if (xx) /* something has changed */ + { + r=CC_HSLtoRGB('R',lpp->h,lpp->s,lpp->l); + g=CC_HSLtoRGB('G',lpp->h,lpp->s,lpp->l); + b=CC_HSLtoRGB('B',lpp->h,lpp->s,lpp->l); + lpp->lpcc->rgbResult=RGB(r,g,b); + CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult); + CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult); + CC_PaintCross(hDlg,lpp->h,lpp->s); + CC_PaintTriangle(hDlg,lpp->l); + } + } + break; + + case 0x2cf: + CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,&lpp->fullsize); + InvalidateRect(hDlg,NULL,NULL); + SetFocus(GetDlgItem(hDlg,0x2bf)); + break; + + case 0x2c8: /* add colors ... column by column */ + cr=PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors); + cr[(lpp->nextuserdef%2)*8 + lpp->nextuserdef/2]=lpp->lpcc->rgbResult; + if (++lpp->nextuserdef==16) + lpp->nextuserdef=0; + CC_PaintUserColorArray(hDlg,2,8,PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors)); + break; + + case 0x2c9: /* resulting color */ + hdc=GetDC(hDlg); + lpp->lpcc->rgbResult=GetNearestColor(hdc,lpp->lpcc->rgbResult); + ReleaseDC(hDlg,hdc); + CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult); + CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult); + r=GetRValue(lpp->lpcc->rgbResult); + g=GetGValue(lpp->lpcc->rgbResult); + b=GetBValue(lpp->lpcc->rgbResult); + lpp->h=CC_RGBtoHSL('H',r,g,b); + lpp->s=CC_RGBtoHSL('S',r,g,b); + lpp->l=CC_RGBtoHSL('L',r,g,b); + CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l); + CC_PaintCross(hDlg,lpp->h,lpp->s); + CC_PaintTriangle(hDlg,lpp->l); + break; + + case 0x40e: /* Help! */ /* The Beatles, 1965 ;-) */ + i=RegisterWindowMessage(MAKE_SEGPTR(HELPMSGSTRING)); + if (lpp->lpcc->hwndOwner) + SendMessage(lpp->lpcc->hwndOwner,i,0,(LPARAM)lpp->lpcc); + if (CC_HookCallChk(lpp->lpcc)) + CallWindowProc((FARPROC)lpp->lpcc->lpfnHook,hDlg, + WM_COMMAND,psh15,(LPARAM)lpp->lpcc); + break; + + case IDOK : + cokmsg=RegisterWindowMessage(MAKE_SEGPTR(COLOROKSTRING)); + if (lpp->lpcc->hwndOwner) + if (SendMessage(lpp->lpcc->hwndOwner,cokmsg,0,(LPARAM)lpp->lpcc)) + break; /* do NOT close */ + + EndDialog (hDlg, 1) ; + return TRUE ; + + case IDCANCEL : + EndDialog (hDlg, 0) ; + return TRUE ; + + } + return FALSE; +} + +/*********************************************************************** + * CC_WMPaint [internal] + */ +static LRESULT CC_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + /* we have to paint dialog children except text and buttons */ + + CC_PaintPredefColorArray(hDlg,6,8); + CC_PaintUserColorArray(hDlg,2,8,PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors)); + CC_PaintColorGraph(hDlg); + CC_PaintLumBar(hDlg,lpp->h,lpp->s); + CC_PaintCross(hDlg,lpp->h,lpp->s); + CC_PaintTriangle(hDlg,lpp->l); + CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult); + + /* special necessary for Wine */ + ValidateRect(GetDlgItem(hDlg,0x2d0),NULL); + ValidateRect(GetDlgItem(hDlg,0x2d1),NULL); + ValidateRect(GetDlgItem(hDlg,0x2c6),NULL); + ValidateRect(GetDlgItem(hDlg,0x2be),NULL); + ValidateRect(GetDlgItem(hDlg,0x2c5),NULL); + /* hope we can remove it later -->FIXME */ + return 0; +} + + +/*********************************************************************** + * CC_WMLButtonDown [internal] + */ +static LRESULT CC_WMLButtonDown(HWND hDlg, WPARAM wParam, LPARAM lParam) +{ + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + int r,g,b,i; + i=0; + if (CC_MouseCheckPredefColorArray(hDlg,0x2d0,6,8,lParam,&lpp->lpcc->rgbResult)) + i=1; + else + if (CC_MouseCheckUserColorArray(hDlg,0x2d1,2,8,lParam,&lpp->lpcc->rgbResult, + PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors))) + i=1; + else + if (CC_MouseCheckColorGraph(hDlg,0x2c6,&lpp->h,&lpp->s,lParam)) + i=2; + else + if (CC_MouseCheckColorGraph(hDlg,0x2be,NULL,&lpp->l,lParam)) + i=2; + if (i==2) + { + r=CC_HSLtoRGB('R',lpp->h,lpp->s,lpp->l); + g=CC_HSLtoRGB('G',lpp->h,lpp->s,lpp->l); + b=CC_HSLtoRGB('B',lpp->h,lpp->s,lpp->l); + lpp->lpcc->rgbResult=RGB(r,g,b); + } + if (i==1) + { + r=GetRValue(lpp->lpcc->rgbResult); + g=GetGValue(lpp->lpcc->rgbResult); + b=GetBValue(lpp->lpcc->rgbResult); + lpp->h=CC_RGBtoHSL('H',r,g,b); + lpp->s=CC_RGBtoHSL('S',r,g,b); + lpp->l=CC_RGBtoHSL('L',r,g,b); + } + if (i) + { + CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult); + CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l); + CC_PaintCross(hDlg,lpp->h,lpp->s); + CC_PaintTriangle(hDlg,lpp->l); + CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult); + return TRUE; + } + return FALSE; +} + +/*********************************************************************** + * ColorDlgProc (COMMDLG.8) + */ +LRESULT ColorDlgProc(HWND hDlg, UINT message, + UINT wParam, LONG lParam) +{ + int res; + struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); + if (message!=WM_INITDIALOG) + { + if (!lpp) + return FALSE; + res=0; + if (CC_HookCallChk(lpp->lpcc)) + res=CallWindowProc((FARPROC)lpp->lpcc->lpfnHook,hDlg,message,wParam,lParam); + if (res) + return res; + } + + /* FIXME: SetRGB message + if (message && message==msetrgb) + return HandleSetRGB(hDlg,lParam); + */ + + switch (message) + { + case WM_INITDIALOG: + return CC_WMInitDialog(hDlg,wParam,lParam); + case WM_NCDESTROY: + /* FIXME: what about lpp->hdcMem ? */ + free(lpp); + SetWindowLong(hDlg, DWL_USER, 0L); /* we don't need it anymore */ + break; + case WM_COMMAND: + if (CC_WMCommand(hDlg, wParam, lParam)) + return TRUE; + break; + case WM_PAINT: + CC_WMPaint(hDlg, wParam, lParam); + break; + case WM_LBUTTONDBLCLK: + if (CC_MouseCheckResultWindow(hDlg,lParam)) + return TRUE; + break; + case WM_MOUSEMOVE: /* FIXME: calculate new hue,sat,lum (if in color graph) */ + break; + case WM_LBUTTONUP: /* FIXME: ClipCursor off (if in color graph)*/ + break; + case WM_LBUTTONDOWN:/* FIXME: ClipCursor on (if in color graph)*/ + if (CC_WMLButtonDown(hDlg, wParam, lParam)) + return TRUE; + break; + } + return FALSE ; +} + diff --git a/misc/winsocket.c b/misc/winsocket.c index 91652e8f8cd..f52c588daff 100644 --- a/misc/winsocket.c +++ b/misc/winsocket.c @@ -11,7 +11,7 @@ #include #include #include -#if defined__svr4__ +#if defined(__svr4__) #include #include #endif diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c index 152ee9a1c43..f678ee42b40 100644 --- a/multimedia/mmsystem.c +++ b/multimedia/mmsystem.c @@ -1900,7 +1900,7 @@ LONG mmioRead(HMMIO hmmio, HPSTR pch, LONG cch) dprintf_mmio(stddeb, "mmioRead(%04X, %p, %ld);\n", hmmio, pch, cch); lpmminfo = (LPMMIOINFO)GlobalLock(hmmio); if (lpmminfo == NULL) return 0; - count = read(LOWORD(lpmminfo->dwReserved2), pch, cch); + count = FILE_Read(LOWORD(lpmminfo->dwReserved2), pch, cch); GlobalUnlock(hmmio); dprintf_mmio(stddeb, "mmioRead // count=%ld\n", count); return count; @@ -2002,7 +2002,7 @@ UINT mmioAdvance(HMMIO hmmio, MMIOINFO FAR* lpmmioinfo, UINT uFlags) lpmminfo = (LPMMIOINFO)GlobalLock(hmmio); if (lpmminfo == NULL) return 0; if (uFlags == MMIO_READ) { - count = read(LOWORD(lpmminfo->dwReserved2), + count = FILE_Read(LOWORD(lpmminfo->dwReserved2), lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer); } if (uFlags == MMIO_WRITE) { @@ -2070,7 +2070,7 @@ UINT mmioDescend(HMMIO hmmio, MMCKINFO FAR* lpck, (uFlags & MMIO_FINDLIST)) { dprintf_mmio(stddeb, "mmioDescend // MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc); while (TRUE) { - if (read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, + if (FILE_Read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) { _llseek(LOWORD(lpmminfo->dwReserved2), dwOldPos, SEEK_SET); GlobalUnlock(hmmio); @@ -2086,7 +2086,7 @@ UINT mmioDescend(HMMIO hmmio, MMCKINFO FAR* lpck, } } else { - if (read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, + if (FILE_Read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) { _llseek(LOWORD(lpmminfo->dwReserved2), dwOldPos, SEEK_SET); GlobalUnlock(hmmio); diff --git a/objects/font.c b/objects/font.c index 41c8d38531c..f9cfc8b6e26 100644 --- a/objects/font.c +++ b/objects/font.c @@ -152,7 +152,9 @@ static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc ) height = 10 * (-height * 9 / 8); * may be we have to use an non linear function */ - height *= -10; + /* assume internal leading is 2 pixels. Else small fonts will become + * very small. */ + height = (height-2) * -10; } else height *= 10; width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY); diff --git a/objects/metafile.c b/objects/metafile.c index f66465cec6f..b68373ab0c0 100644 --- a/objects/metafile.c +++ b/objects/metafile.c @@ -648,7 +648,7 @@ BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen) GlobalUnlock(mf->hMetaHdr); mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE); mh = (METAHEADER *)GlobalLock(mf->hMetaHdr); - memcpy(mh + mh->mtSize * 2, mr, rlen); + memcpy((WORD *)mh + mh->mtSize, mr, rlen); } else if (mh->mtType == 1) /* disk based metafile */ { diff --git a/programs/progman/main.c b/programs/progman/main.c index e9906ffce5d..561fc274756 100644 --- a/programs/progman/main.c +++ b/programs/progman/main.c @@ -62,8 +62,8 @@ int PASCAL WinMain (HANDLE hInstance, HANDLE prev, LPSTR cmdline, int show) } #endif - /* Select Language */ -#ifdef WINELIB + /* Select Language (FIXME) */ +#ifndef WINELIB Globals.lpszLanguage = langNames[Options.language]; #else Globals.lpszLanguage = "En"; diff --git a/programs/progman/string.c b/programs/progman/string.c index f33941b40ea..cb6e16081e0 100644 --- a/programs/progman/string.c +++ b/programs/progman/string.c @@ -120,8 +120,8 @@ VOID STRING_SelectLanguageByNumber(UINT num) if (Globals.hMainMenu) DestroyMenu(Globals.hMainMenu); Globals.hMainMenu = hMainMenu; -#ifdef WINELIB - /* Update system menus */ +#ifndef WINELIB + /* Update system menus (FIXME) */ for (i = 0; langNames[i] && lstrcmp(lang, langNames[i]);) i++; if (langNames[i]) Options.language = i; diff --git a/rc/parser.h b/rc/parser.h index 38e5028e157..c0d2d27feab 100644 --- a/rc/parser.h +++ b/rc/parser.h @@ -105,7 +105,3 @@ void set_out_file(char*); extern int verbose; -#ifdef __sun__ -#define strtoul strtol -#endif - diff --git a/resources/TODO b/resources/TODO index e391bd37aa5..31be6f58367 100644 --- a/resources/TODO +++ b/resources/TODO @@ -27,3 +27,27 @@ flags (WS_??? etc): They control how the dialog behaves. Things like: Frans van Dorsselaer dorssel@rulhm1.LeidenUniv.nl +*************************************************************** +1996, April, 7th + +Subject: ChooseColor + =========== + +Today I introduced ChooseColor() to commdlg.c. +Because this old resource was insufficient I wrote a new one +(including some new static contols). + +Please delete the old CHOOSECOLOR in YOUR sysres_??.rc +and insert the new CHOOSECOLOR from sysres_En.rc to YOUR +language file and translate this as you like it - +otherwise you'll get an undefined behavour. + +Today it works well for: +* English +* German +...to be continued...... + +Thank you. + +Albrecht Kleine +kleine@ak.sax.de diff --git a/resources/sysres_De.rc b/resources/sysres_De.rc index abb8f604303..b20f6b8b7c9 100644 --- a/resources/sysres_De.rc +++ b/resources/sysres_De.rc @@ -144,24 +144,37 @@ FONT 8, "Helv" } -CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 200 +CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 300, 200 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Farbe" FONT 8, "Helv" { - LTEXT "&Standardfarben:", 1088, 6, 6, 40, 9 - LTEXT "S&elbstdefinierte Farben:", 1089, 6, 126, 40, 9 - LTEXT "Farbe|Re&in", 1090, 100, 146, 40, 9 - LTEXT "&Ton:", 1091, 150, 126, 40, 9 - LTEXT "&Sättigung:", 1092, 150, 146, 40, 9 - LTEXT "&Helligkeit:", 1093, 150, 166, 40, 9 - LTEXT "&Rot:", 1094, 150, 126, 40, 9 - LTEXT "&Grün:", 1095, 150, 146, 40, 9 - LTEXT "Bl&au:", 1096, 150, 166, 40, 9 - DEFPUSHBUTTON "Ok", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Selbstdefinierte Farbe &hinzufügen", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "Selbstdefinierte Farbe &entfernen", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "Abbrechen", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP + LTEXT "Gr&undfarben:", 1088, 4, 4, 140, 10 + LTEXT "Selbs&tdefinierte Farben:", 1089, 4, 106, 140, 10 + LTEXT "Farbe | B&asis", 1090, 150, 151, 48, 10 + LTEXT "&Rot:", 726 ,249,126,24,10 + EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Grün:",727/*1095*/,249,140,24,10 + EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Blau:",728 /*1096*/,249,154,24,10 + EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Farbe:" ,723 /*1091*/,202,126,22,10 + EDITTEXT 703, 226,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Sätt:" ,724 /*1092*/,202,140,22,10 + EDITTEXT 704, 226,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "H&ell:" ,725 /*1093*/,202,154,22,10 + EDITTEXT 705, 226,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + CONTROL "" ,720,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,14,140,86 + CONTROL "" ,721,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,116,140,28 + CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116 + CONTROL "" ,702,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 278,4,8,116 + CONTROL "" ,709,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,124,40,26 + DEFPUSHBUTTON "Ok", 1, 4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Abbrechen", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "&Hilfe", 1038,100,166, 44, 14 + PUSHBUTTON "Farbe hin&zufügen", 712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "Farben &definieren >>", 719/*1025*/, 4, 150, 142, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "&a",713,300,200,4,14 /* just a dummy: 'a' is like &a in "B&asis" */ } diff --git a/resources/sysres_En.rc b/resources/sysres_En.rc index b9187717941..aba679af859 100644 --- a/resources/sysres_En.rc +++ b/resources/sysres_En.rc @@ -144,24 +144,37 @@ FONT 8, "Helv" } -CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 200 +CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 300, 200 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Color" FONT 8, "Helv" { - LTEXT "&Basic Colors:", 1088, 6, 6, 40, 9 - LTEXT "&Custom Colors:", 1089, 6, 126, 40, 9 - LTEXT "Color|Sol&id", 1090, 100, 146, 40, 9 - LTEXT "&Hue:", 1091, 150, 126, 40, 9 - LTEXT "&Sat:", 1092, 150, 146, 40, 9 - LTEXT "&Lum:", 1093, 150, 166, 40, 9 - LTEXT "&Red:", 1094, 150, 126, 40, 9 - LTEXT "&Green:", 1095, 150, 146, 40, 9 - LTEXT "Bl&ue:", 1096, 150, 166, 40, 9 - DEFPUSHBUTTON "Ok", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "&Add to Custom Colors", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "&Delete Custom Colors", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "Cancel", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP + LTEXT "&Basic Colors:", 1088, 4, 4, 140, 10 + LTEXT "&Custom Colors:", 1089, 4, 106, 140, 10 + LTEXT "Color | Sol&id", 1090, 150, 151, 48, 10 + LTEXT "&Red:", 726 /*1094*/,249,126,24,10 + EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Green:",727/*1095*/,249,140,24,10 + EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Blue:",728 /*1096*/,249,154,24,10 + EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Hue:" ,723 /*1091*/,202,126,22,10 + EDITTEXT 703, 226,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Sat:" ,724 /*1092*/,202,140,22,10 + EDITTEXT 704, 226,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + LTEXT "&Lum:" ,725 /*1093*/,202,154,22,10 + EDITTEXT 705, 226,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP + CONTROL "" ,720,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,14,140,86 + CONTROL "" ,721,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,116,140,28 + CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116 + CONTROL "" ,702,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 278,4,8,116 + CONTROL "" ,709,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,124,40,26 + DEFPUSHBUTTON "Ok", 1, 4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Cancel", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "Help", 1038,100,166, 44, 14 + PUSHBUTTON "&Add to Custom Colors", 712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "&Define Custom Colors >>", 719/*1025*/, 4, 150, 142, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "&i",713,300,200,4,14 /* just a dummy: 'i' is like &i in "sol&id" */ } diff --git a/resources/sysres_It.rc b/resources/sysres_It.rc index 15a0136115c..91ba4565802 100644 --- a/resources/sysres_It.rc +++ b/resources/sysres_It.rc @@ -30,7 +30,7 @@ END SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 223, 200 STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Informazioni su %s" -FONT 10, "Sistema" +FONT 10, "System" { DEFPUSHBUTTON "OK", 1, 91, 180, 40, 14 CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 215, 140 @@ -44,10 +44,10 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Apri" FONT 8, "Helv" { - LTEXT "File &Nome:", 1090, 6, 6, 76, 9 + LTEXT "&Nome file:", 1090, 6, 6, 76, 9 EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT | WS_BORDER | WS_TABSTOP LISTBOX 1120, 6, 32, 90, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP - LTEXT "&Directories:", -1, 110, 6, 92, 9 + LTEXT "&Percorso:", -1, 110, 6, 92, 9 LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX | WS_GROUP LISTBOX 1121, 110, 32, 92, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP LTEXT "Files di &Tipo:", 1089, 6, 104, 90, 9 @@ -57,7 +57,7 @@ FONT 8, "Helv" DEFPUSHBUTTON "Apri", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Annulla", 2, 208, 24, 56, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Aiuto", 1038, 208, 46, 56, 14, WS_GROUP | WS_TABSTOP - CHECKBOX "Solo &Lettura", 1040, 208, 68, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + CHECKBOX "Solo &Lettura", 1040, 208, 68, 52, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP } @@ -66,17 +66,17 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Salva con nome ..." FONT 8, "Helv" { - LTEXT "File &Nome:", 1090, 6, 6, 76, 9 + LTEXT "&Nome file:", 1090, 6, 6, 76, 9 EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT | WS_BORDER | WS_TABSTOP LISTBOX 1120, 6, 32, 90, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP - LTEXT "&Directories:", -1, 110, 6, 92, 9 + LTEXT "&Percorso:", -1, 110, 6, 92, 9 LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX | WS_GROUP LISTBOX 1121, 110, 32, 92, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP LTEXT "Files di &Tipo:", 1089, 6, 104, 90, 9 COMBOBOX 1136, 6, 114, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP LTEXT "&Unita':", 1091, 110, 104, 92, 9 COMBOBOX 1137, 110, 114, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "Save As", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + DEFPUSHBUTTON "Salva come", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Cancel", 2, 208, 24, 56, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Help", 1038, 208, 46, 56, 14, WS_GROUP | WS_TABSTOP CHECKBOX "&Read Only", 1040, 208, 68, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP @@ -106,29 +106,29 @@ FONT 8, "Helv" } -PRINT_SETUP DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 134 +PRINT_SETUP DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 274, 154 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Configurazione Stampante" FONT 8, "Helv" { - GROUPBOX "Stampante", 1072, 6, 10, 180, 65, BS_GROUPBOX - RADIOBUTTON "Stampante &Preferita", 1056, 16, 20, 80, 12 + GROUPBOX "Stampante", 1072, 6, 10, 180, 72, BS_GROUPBOX + RADIOBUTTON "Stampante &Preferita", 1056, 16, 20, 78, 12 LTEXT "[none]", 1088, 35, 35, 120, 9 - RADIOBUTTON "Stampante &Specifica", 1057, 16, 50, 80, 12 + RADIOBUTTON "Stampante &Specifica", 1057, 16, 50, 78, 12 COMBOBOX 1136, 35, 65, 149, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "Ok", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP PUSHBUTTON "Annulla", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Installa", 1024, 206, 46, 56, 14, WS_GROUP | WS_TABSTOP GROUPBOX "Orientamento", 1073, 6, 85, 100, 50, BS_GROUPBOX - RADIOBUTTON "&Verticale", 1058, 50, 100, 40, 12 - RADIOBUTTON "&Orizzontale", 1059, 50, 115, 40, 12 + RADIOBUTTON "&Verticale", 1058, 50, 100, 42, 12 + RADIOBUTTON "&Orizzontale", 1059, 50, 115, 50, 12 ICON "LANDSCAP", 1097, 10, 95, 32, 32 ICON "PORTRAIT", 1098, 10, 95, 32, 32 - GROUPBOX "Carta", 1074, 120, 85, 180, 50, BS_GROUPBOX - LTEXT "&Dimensione", 1089, 130, 95, 30, 9 - LTEXT "&Sorgente", 1090, 130, 110, 30, 9 - COMBOBOX 1137, 155, 95, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP - COMBOBOX 1138, 155, 110, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Carta", 1074, 120, 85, 150, 50, BS_GROUPBOX + LTEXT "&Dimensione", 1089, 130, 100, 30, 9 + LTEXT "&Sorgente", 1090, 130, 115, 30, 9 + COMBOBOX 1137, 168, 95, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP + COMBOBOX 1138, 168, 110, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP } @@ -159,7 +159,7 @@ FONT 8, "Helv" LTEXT "&Verde:", 1095, 150, 146, 40, 9 LTEXT "Bl&u:", 1096, 150, 166, 40, 9 DEFPUSHBUTTON "Ok", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "&Aggiugni ai Colori Utente", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP + PUSHBUTTON "&Aggiungi ai Colori Utente", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Cancella Colori Utente", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "Annulla", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP } @@ -170,14 +170,14 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Trova" FONT 8, "Helv" { - LTEXT "Tro&va cosa:", -1, 4, 8, 42, 8 + LTEXT "Tro&va:", -1, 4, 8, 42, 8 EDITTEXT 1152, 47, 7, 128, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP CHECKBOX "&Parola Intera", 1040, 4, 26, 100, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP - CHECKBOX "&Maiuscole/Minuscole", 1041, 4, 42, 64, 12, BS_AUTOCHECKBOX | WS_TABSTOP + CHECKBOX "&Maiuscole/Minuscole", 1041, 4, 42, 74, 12, BS_AUTOCHECKBOX | WS_TABSTOP GROUPBOX "Direzione", 1072, 107, 26, 68, 28 - CONTROL "&Su", 1056, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 111, 38, 20, 12 - CONTROL "&Giu'", 1057, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 138, 38, 30, 12 - DEFPUSHBUTTON "&Trova Prossimo", 1, 182, 5, 50, 14, WS_GROUP | WS_TABSTOP + CONTROL "&Su", 1056, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 111, 38, 24, 12 + CONTROL "&Giu'", 1057, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 142, 38, 28, 12 + DEFPUSHBUTTON "&Trova Prossimo", 1, 180, 5, 54, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "Annulla", 2, 182, 23, 50, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Aiuto", 1038, 182, 45, 50, 14, WS_GROUP | WS_TABSTOP } @@ -188,7 +188,7 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Cambia" FONT 8, "Helv" { - LTEXT "Tro&va cosa:", -1, 4, 9, 48, 8 + LTEXT "Tro&va:", -1, 4, 9, 48, 8 EDITTEXT 1152, 54, 7, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP LTEXT "Ca&mbia con:", -1, 4, 26, 48, 8 EDITTEXT 1153, 54, 24, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP diff --git a/tools/build.c b/tools/build.c index 9e994f0a4ba..dfa2d402c1c 100644 --- a/tools/build.c +++ b/tools/build.c @@ -635,6 +635,9 @@ static void BuildModule16( int max_code_offset, int max_data_offset ) pModule->nrname_handle = 0; pModule->min_swap_area = 0; pModule->expected_version = 0x030a; + pModule->pe_module = NULL; + pModule->self = 0; + pModule->self_loading_sel = 0; /* File information */ @@ -772,14 +775,12 @@ static void BuildModule32(void) { char *buffer; NE_MODULE *pModule; - NE_WIN32_EXTRAINFO *pExtraInfo; OFSTRUCT *pFileInfo; BYTE *pstr; WORD *pword; /* Module layout: * NE_MODULE Module - * NE_WIN32_EXTRAINFO Win32 module extra info * OFSTRUCT File information * SEGTABLEENTRY Segment table (empty) * WORD[2] Resource table (empty) @@ -817,15 +818,13 @@ static void BuildModule32(void) pModule->nrname_handle = 0; pModule->min_swap_area = 0; pModule->expected_version = 0x030a; - - /* Win32 extra info */ - - pExtraInfo = (NE_WIN32_EXTRAINFO *)(pModule + 1); - pExtraInfo->pe_module = 0; + pModule->pe_module = NULL; + pModule->self = 0; + pModule->self_loading_sel = 0; /* File information */ - pFileInfo = (OFSTRUCT *)(pExtraInfo + 1); + pFileInfo = (OFSTRUCT *)(pModule + 1); pModule->fileinfo = (int)pFileInfo - (int)pModule; memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) ); pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) diff --git a/win32/Makefile.in b/win32/Makefile.in index 2ff2ccffbf5..b563e7e5489 100644 --- a/win32/Makefile.in +++ b/win32/Makefile.in @@ -11,7 +11,6 @@ C_SRCS = \ except.c \ file.c \ gdi32.c \ - heap.c \ init.c \ memory.c \ newfns.c \ diff --git a/win32/heap.c b/win32/heap.c deleted file mode 100644 index 33e9dbbdcbc..00000000000 --- a/win32/heap.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Win32 kernel functions - * - * Copyright 1995 Thomas Sandford - * Copyright 1995 Martin von Löwis - */ - -#include -#include -#include -#include -#include -#include -#include "windows.h" -#include "winerror.h" -#include "kernel32.h" -#include "handle32.h" -#include "winbase.h" -#include "stddebug.h" -#include "debug.h" - -#define HEAP_ZERO_MEMORY 0x8 - -/* FIXME: these functions do *not* implement the win32 API properly. They -are here merely as "get you going" aids */ -/*********************************************************************** - * HeapAlloc (KERNEL32.222) - * - */ -LPVOID SIMPLE_HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes) - -{ - void *result; - - result = malloc(dwBytes); - if(result && (dwFlags & HEAP_ZERO_MEMORY)) - memset(result, 0, dwBytes); - return result; -} - -HANDLE32 HeapCreate(DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize) -{ - LPVOID start; - HEAP_OBJECT *ret; - HEAPITEM_OBJECT *item; - if(dwInitialSize<4096) - return 0; - start = VirtualAlloc(0,dwMaximumSize, MEM_RESERVE, PAGE_READWRITE); - if(!start) - return 0; - if(!VirtualAlloc(start,dwInitialSize, MEM_COMMIT, PAGE_READWRITE)) - { - VirtualFree(start,dwMaximumSize,MEM_RELEASE); - return 0; - } - ret=CreateKernelObject(sizeof(HEAP_OBJECT)); - ret->common.magic=KERNEL_OBJECT_HEAP; - ret->start=start; - ret->size=dwInitialSize; - ret->maximum=dwMaximumSize; - ret->flags=flOptions; - item=start; - item->common.magic=KERNEL_OBJECT_HEAPITEM; - item->next=item->prev=0; - item->heap=ret; - - ret->first=ret->last=item; - - return (HANDLE32)ret; -} - -BOOL HeapDestroy(HEAP_OBJECT *h) -{ - /* FIXME: last error */ - if(h->common.magic!=KERNEL_OBJECT_HEAP) - return 0; - h->common.magic=0; - VirtualFree(h->start,h->size,MEM_RELEASE); - ReleaseKernelObject(h); - return 1; -} - - -static BOOL HEAP_GrowHeap(HEAP_OBJECT *h,DWORD size) -{ - HEAPITEM_OBJECT *last; - /* FIXME: last error */ - if(size > h->maximum-h->size) - return 0; - if(!VirtualAlloc(h->start+h->size,size,MEM_COMMIT,PAGE_READWRITE)) - return 0; - /* FIXME: consolidate with previous item */ - last=h->start+size; - h->size+=size; - h->last->next=last; - last->prev=h->last; - last->next=0; - h->last=last; - last->common.magic=KERNEL_OBJECT_HEAPITEM; - last->heap=h; - return 1; -} - - -LPVOID HeapAlloc(HEAP_OBJECT *h,DWORD dwFlags,DWORD dwBytes) -{ - HEAPITEM_OBJECT *it,*next,*prev; - /* FIXME: last error */ - if(!h) - return SIMPLE_HeapAlloc(h,dwFlags,dwBytes); - if(h->common.magic!=KERNEL_OBJECT_HEAP) - return 0; - /* align to DWORD */ - dwBytes = (dwBytes + 3) & ~3; - for(it=h->first;it;it=it->next) - { - if(it->size>dwBytes+sizeof(HEAPITEM_OBJECT)) - break; - } - if(!it) - { - if(!HEAP_GrowHeap(h,dwBytes)) - return 0; - it=h->last; - } - next = it->next; - prev = it->prev; - if(it->size > dwBytes+2*sizeof(HEAPITEM_OBJECT)) - { /* split item */ - HEAPITEM_OBJECT *next=(HEAPITEM_OBJECT*)((char*)(it+1)+dwBytes); - next->common.magic=KERNEL_OBJECT_HEAPITEM; - next->size=it->size-sizeof(HEAPITEM_OBJECT)-dwBytes; - next->next = it->next; - } - if(next) - next->prev=prev; - else - h->last=prev; - if(prev) - prev->next=next; - else - h->first=next; - /* Allocated item is denoted by self-referencing */ - it->next=it->prev=it; - return (LPVOID)(it+1); -} - -BOOL HeapFree(HEAP_OBJECT *h,DWORD dwFlags,LPVOID lpMem) -{ - HEAPITEM_OBJECT *item,*prev,*next; - item = (HEAPITEM_OBJECT*)lpMem - 1; - if(item->common.magic != KERNEL_OBJECT_HEAP) - return 0; - for(next=item;(caddr_t)next<(caddr_t)h->start+h->size; - next=(HEAPITEM_OBJECT*)((char*)next+next->size)) - if(next!=next->next) - break; - if((caddr_t)next>=(caddr_t)h->start+h->size) - next=0; - if(next) - prev=next->prev; - else - prev=h->last; - /* consolidate with previous */ - if(prev && (char*)prev+prev->size==(char*)item) - { - prev->size+=item->size; - item=prev; - prev=item->prev; - } - /* consolidate with next */ - if(next && (char*)item+item->size==(char*)next) - { - item->size+=next->size; - next=next->next; - } - if(prev) - { - item->prev=prev; - prev->next=item; - } else - h->first=item; - if(next) - { - item->next=next; - next->prev=item; - }else - h->last=item; - return 1; -} - diff --git a/win32/init.c b/win32/init.c index 0d53749c9d0..bf38b1d1541 100644 --- a/win32/init.c +++ b/win32/init.c @@ -30,7 +30,7 @@ static int CreateStdHandles(void); /********************************************************************* * CloseHandle (KERNEL32.23) */ -BOOL CloseHandle(HANDLE32 handle) +BOOL CloseHandle(KERNEL_OBJECT *handle) { int rc; diff --git a/win32/resource.c b/win32/resource.c index 7d55ec9dece..dfe55370ea7 100644 --- a/win32/resource.c +++ b/win32/resource.c @@ -93,7 +93,7 @@ PIMAGE_RESOURCE_DIRECTORY GetResDirEntry(PIMAGE_RESOURCE_DIRECTORY resdirptr, HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type ) { #ifndef WINELIB - struct pe_data *pe; + PE_MODULE *pe; NE_MODULE *pModule; PIMAGE_RESOURCE_DIRECTORY resdirptr; DWORD root; @@ -105,9 +105,9 @@ HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type ) dprintf_resource( stddeb, " name=" ); PrintId( name ); dprintf_resource( stddeb, "\n" ); - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0; /* FIXME? */ - if (!(pe = NE_WIN32_MODULE(pModule)) || !pe->pe_resource) return 0; + if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0; resdirptr = (PIMAGE_RESOURCE_DIRECTORY) pe->pe_resource; root = (DWORD) resdirptr; @@ -117,8 +117,10 @@ HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type ) return 0; result = GetResDirEntry(resdirptr, (LPCWSTR)language, root); /* Try LANG_NEUTRAL, too */ - if(!result) - return GetResDirEntry(resdirptr, (LPCWSTR)0, root); + if(!result) + return GetResDirEntry(resdirptr, (LPCWSTR)0, root); + return result; + #else return LIBRES_FindResource( hModule, name, type ); #endif @@ -131,17 +133,17 @@ HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type ) HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc ) { #ifndef WINELIB - struct pe_data *pe; NE_MODULE *pModule; + PE_MODULE *pe; hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n", hModule, hRsrc ); if (!hRsrc) return 0; - if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0; + if (!(pModule = MODULE_GetPtr( hModule ))) return 0; if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0; /* FIXME? */ - if (!(pe = NE_WIN32_MODULE(pModule)) || !pe->pe_resource) return 0; + if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0; return (HANDLE32) (pe->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData); #else return LIBRES_LoadResource( hModule, hRsrc ); diff --git a/win32/thread.c b/win32/thread.c index 5e203c13735..3d958d09f37 100644 --- a/win32/thread.c +++ b/win32/thread.c @@ -48,12 +48,18 @@ void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit) void WINAPI EnterCriticalSection(CRITICAL_SECTION* lpCrit) { - return; + if (lpCrit->LockCount) + fprintf( stderr, "Error: re-entering critical section %08lx\n", + (DWORD)lpCrit ); + lpCrit->LockCount++; } void WINAPI LeaveCriticalSection(CRITICAL_SECTION* lpCrit) { - return; + if (!lpCrit->LockCount) + fprintf( stderr, "Error: leaving critical section %08lx again\n", + (DWORD)lpCrit ); + lpCrit->LockCount--; } void WINAPI DeleteCriticalSection(CRITICAL_SECTION* lpCrit) diff --git a/win32/time.c b/win32/time.c index 8dd88fc2a49..610d4a6067d 100644 --- a/win32/time.c +++ b/win32/time.c @@ -84,6 +84,6 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION tzinfo) VOID Sleep(DWORD cMilliseconds) { if(cMilliseconds == INFINITE) - while(1) { /* Spin forever */ } + while(1) sleep(1000); /* Spin forever */ usleep(cMilliseconds*1000); } diff --git a/windows/dialog.c b/windows/dialog.c index a3fc33da40f..ee3f402f383 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -69,14 +69,20 @@ HWND DIALOG_GetFirstTabItem( HWND hwndDlg ) * DIALOG_GetControl * * Return the class and text of the control pointed to by ptr, - * and return a pointer to the next control. + * fill the header structure and return a pointer to the next control. */ -static SEGPTR DIALOG_GetControl( SEGPTR ptr, SEGPTR *class, SEGPTR *text ) +static SEGPTR DIALOG_GetControl( SEGPTR ptr, DLGCONTROLHEADER *header, + SEGPTR *class, SEGPTR *text ) { unsigned char *base = (unsigned char *)PTR_SEG_TO_LIN( ptr ); unsigned char *p = base; - p += 14; /* size of control header */ + header->x = GET_WORD(p); p += sizeof(WORD); + header->y = GET_WORD(p); p += sizeof(WORD); + header->cx = GET_WORD(p); p += sizeof(WORD); + header->cy = GET_WORD(p); p += sizeof(WORD); + header->id = GET_WORD(p); p += sizeof(WORD); + header->style = GET_DWORD(p); p += sizeof(DWORD); if (*p & 0x80) { @@ -92,7 +98,7 @@ static SEGPTR DIALOG_GetControl( SEGPTR ptr, SEGPTR *class, SEGPTR *text ) if (*p == 0xff) { /* Integer id, not documented (?). Only works for SS_ICON controls */ - *text = MAKEINTRESOURCE( p[1] + 256 * p[2] ); + *text = MAKEINTRESOURCE( GET_WORD(p+1) ); p += 4; } else @@ -115,14 +121,18 @@ static SEGPTR DIALOG_ParseTemplate( SEGPTR template, DLGTEMPLATE * result ) unsigned char *base = (unsigned char *)PTR_SEG_TO_LIN(template); unsigned char * p = base; - result->header = *(DLGTEMPLATEHEADER *)p; - p += 13; + result->style = GET_DWORD(p); p += sizeof(DWORD); + result->nbItems = *p++; + result->x = GET_WORD(p); p += sizeof(WORD); + result->y = GET_WORD(p); p += sizeof(WORD); + result->cx = GET_WORD(p); p += sizeof(WORD); + result->cy = GET_WORD(p); p += sizeof(WORD); /* Get the menu name */ if (*p == 0xff) { - result->menuName = MAKEINTRESOURCE( p[1] + 256 * p[2] ); + result->menuName = MAKEINTRESOURCE( GET_WORD(p+1) ); p += 3; } else if (*p) @@ -149,9 +159,9 @@ static SEGPTR DIALOG_ParseTemplate( SEGPTR template, DLGTEMPLATE * result ) /* Get the font name */ - if (result->header.style & DS_SETFONT) + if (result->style & DS_SETFONT) { - result->pointSize = *(WORD *)p; + result->pointSize = GET_WORD(p); p += sizeof(WORD); result->faceName = template + (WORD)(p - base); p += strlen(p) + 1; @@ -166,9 +176,9 @@ static SEGPTR DIALOG_ParseTemplate( SEGPTR template, DLGTEMPLATE * result ) */ static void DIALOG_DisplayTemplate( DLGTEMPLATE * result ) { - dprintf_dialog(stddeb, "DIALOG %d, %d, %d, %d\n", result->header.x, result->header.y, - result->header.cx, result->header.cy ); - dprintf_dialog(stddeb, " STYLE %08lx\n", result->header.style ); + dprintf_dialog(stddeb, "DIALOG %d, %d, %d, %d\n", result->x, result->y, + result->cx, result->cy ); + dprintf_dialog(stddeb, " STYLE %08lx\n", result->style ); dprintf_dialog( stddeb, " CAPTION '%s'\n", (char *)PTR_SEG_TO_LIN(result->caption) ); @@ -184,7 +194,7 @@ static void DIALOG_DisplayTemplate( DLGTEMPLATE * result ) else if (LOWORD(result->menuName)) dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) ); - if (result->header.style & DS_SETFONT) + if (result->style & DS_SETFONT) dprintf_dialog( stddeb, " FONT %d,'%s'\n", result->pointSize, (char *)PTR_SEG_TO_LIN(result->faceName) ); } @@ -264,7 +274,7 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate, /* Create custom font if needed */ - if (template.header.style & DS_SETFONT) + if (template.style & DS_SETFONT) { /* The font height must be negative as it is a point size */ /* (see CreateFont() documentation in the Windows SDK). */ @@ -293,26 +303,26 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate, /* Create dialog main window */ rect.left = rect.top = 0; - rect.right = template.header.cx * xUnit / 4; - rect.bottom = template.header.cy * yUnit / 8; - if (template.header.style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME; - AdjustWindowRectEx( &rect, template.header.style, + rect.right = template.cx * xUnit / 4; + rect.bottom = template.cy * yUnit / 8; + if (template.style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME; + AdjustWindowRectEx( &rect, template.style, hMenu ? TRUE : FALSE , exStyle ); rect.right -= rect.left; rect.bottom -= rect.top; - if ((INT)template.header.x == CW_USEDEFAULT) + if ((INT)template.x == CW_USEDEFAULT) rect.left = rect.top = CW_USEDEFAULT; else { - rect.left += template.header.x * xUnit / 4; - rect.top += template.header.y * yUnit / 8; - if (!(template.header.style & DS_ABSALIGN)) + rect.left += template.x * xUnit / 4; + rect.top += template.y * yUnit / 8; + if (!(template.style & DS_ABSALIGN)) ClientToScreen( owner, (POINT *)&rect ); } hwnd = CreateWindowEx( exStyle, template.className, template.caption, - template.header.style & ~WS_VISIBLE, + template.style & ~WS_VISIBLE, rect.left, rect.top, rect.right, rect.bottom, owner, hMenu, hInst, (SEGPTR)0 ); if (!hwnd) @@ -348,15 +358,15 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate, dlgInfo->msgResult = 0; /* This is used to store the default button id */ dlgInfo->hDialogHeap = 0; - for (i = 0; i < template.header.nbItems; i++) + for (i = 0; i < template.nbItems; i++) { - DLGCONTROLHEADER *header; + DLGCONTROLHEADER header; SEGPTR className, winName; HWND hwndDefButton = 0; char buffer[10]; - header = (DLGCONTROLHEADER *)PTR_SEG_TO_LIN( headerPtr ); - headerPtr = DIALOG_GetControl( headerPtr, &className, &winName ); + headerPtr = DIALOG_GetControl( headerPtr, &header, + &className, &winName ); if (!HIWORD(className)) { @@ -381,12 +391,12 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate, else dprintf_dialog(stddeb,"%04x", LOWORD(winName) ); dprintf_dialog(stddeb," %d, %d, %d, %d, %d, %08lx\n", - header->id, header->x, header->y, - header->cx, header->cy, header->style ); + header.id, header.x, header.y, + header.cx, header.cy, header.style ); if (HIWORD(className) && !strcmp( (char *)PTR_SEG_TO_LIN(className), "EDIT") && - ((header->style & DS_LOCALEDIT) != DS_LOCALEDIT)) + ((header.style & DS_LOCALEDIT) != DS_LOCALEDIT)) { if (!dlgInfo->hDialogHeap) { @@ -399,23 +409,23 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate, LocalInit(dlgInfo->hDialogHeap, 0, 0xffff); } hwndCtrl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, className, winName, - header->style | WS_CHILD, - header->x * xUnit / 4, - header->y * yUnit / 8, - header->cx * xUnit / 4, - header->cy * yUnit / 8, - hwnd, (HMENU)header->id, + header.style | WS_CHILD, + header.x * xUnit / 4, + header.y * yUnit / 8, + header.cx * xUnit / 4, + header.cy * yUnit / 8, + hwnd, (HMENU)header.id, dlgInfo->hDialogHeap, (SEGPTR)0 ); } else { hwndCtrl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, className, winName, - header->style | WS_CHILD, - header->x * xUnit / 4, - header->y * yUnit / 8, - header->cx * xUnit / 4, - header->cy * yUnit / 8, - hwnd, (HMENU)header->id, + header.style | WS_CHILD, + header.x * xUnit / 4, + header.y * yUnit / 8, + header.cx * xUnit / 4, + header.cy * yUnit / 8, + hwnd, (HMENU)header.id, hInst, (SEGPTR)0 ); } @@ -454,7 +464,7 @@ HWND CreateDialogIndirectParam( HINSTANCE hInst, SEGPTR dlgTemplate, SendMessage( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 ); if (SendMessage( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param )) SetFocus( dlgInfo->hwndFocus ); - if (template.header.style & WS_VISIBLE) ShowWindow(hwnd, SW_SHOW); + if (template.style & WS_VISIBLE) ShowWindow(hwnd, SW_SHOW); return hwnd; } diff --git a/windows/event.c b/windows/event.c index 19fa10a0d2f..098d8766a7e 100644 --- a/windows/event.c +++ b/windows/event.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -20,6 +19,7 @@ #include "win.h" #include "class.h" #include "clipboard.h" +#include "debugger.h" #include "options.h" #include "queue.h" #include "winpos.h" @@ -317,7 +317,7 @@ static void EVENT_key( XKeyEvent *event ) /* Ctrl-Alt-Return enters the debugger */ if ((keysym == XK_Return) && (event->type == KeyPress) && (event->state & ControlMask) && (event->state & Mod1Mask)) - kill( getpid(), SIGHUP ); + DEBUG_EnterDebugger(); xkey = LOWORD(keysym); key_type = HIBYTE(xkey); @@ -451,8 +451,8 @@ static void EVENT_ButtonPress( XButtonEvent *event ) int buttonNum = event->button - 1; if (buttonNum >= NB_BUTTONS) return; - MouseButtonsStates[buttonNum] = TRUE; - AsyncMouseButtonsStates[buttonNum] = TRUE; + MouseButtonsStates[buttonNum] = 0x8000; + AsyncMouseButtonsStates[buttonNum] = 0x8000; hardware_event( messages[buttonNum], EVENT_XStateToKeyState( event->state ), 0L, event->x_root - desktopX, event->y_root - desktopY, diff --git a/windows/keyboard.c b/windows/keyboard.c index bdf8030ff43..7dae63072d1 100644 --- a/windows/keyboard.c +++ b/windows/keyboard.c @@ -40,9 +40,9 @@ INT GetKeyState(INT keycode) void GetKeyboardState(BYTE FAR *lpKeyState) { if (lpKeyState != NULL) { - KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0]; - KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1]; - KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2]; + KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8; + KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8; + KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8; memcpy(lpKeyState, KeyStateTable, 256); } } @@ -54,9 +54,9 @@ void SetKeyboardState(BYTE FAR *lpKeyState) { if (lpKeyState != NULL) { memcpy(KeyStateTable, lpKeyState, 256); - MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON]; - MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON]; - MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON]; + MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON]? 0x8000: 0; + MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON]? 0x8000: 0; + MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON]? 0x8000: 0; } } @@ -80,15 +80,15 @@ int GetAsyncKeyState(int nKey) switch (nKey) { case VK_LBUTTON: retval = AsyncMouseButtonsStates[0] | - (MouseButtonsStates[0] << 8); + MouseButtonsStates[0]? 0x0001: 0; break; case VK_MBUTTON: retval = AsyncMouseButtonsStates[1] | - (MouseButtonsStates[1] << 8); + MouseButtonsStates[1]? 0x0001: 0; break; case VK_RBUTTON: retval = AsyncMouseButtonsStates[2] | - (MouseButtonsStates[2] << 8); + MouseButtonsStates[2]? 0x0001: 0; break; default: retval = AsyncKeyStateTable[nKey] | diff --git a/windows/message.c b/windows/message.c index 6a88fc6eb05..d1ac19576d7 100644 --- a/windows/message.c +++ b/windows/message.c @@ -81,32 +81,28 @@ static BOOL MSG_TranslateMouseMsg( MSG *msg, BOOL remove ) hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd ); msg->hwnd = pWnd->hwndSelf; - if (hittest != HTERROR) + if ((hittest != HTERROR) && mouseClick) { + HWND hwndTop = WIN_GetTopParent( msg->hwnd ); + /* Send the WM_PARENTNOTIFY message */ - if (mouseClick) WIN_SendParentNotify( msg->hwnd, msg->message, 0, - MAKELONG( msg->pt.x, msg->pt.y ) ); + WIN_SendParentNotify( msg->hwnd, msg->message, 0, + MAKELONG( msg->pt.x, msg->pt.y ) ); /* Activate the window if needed */ - if (mouseClick) + if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow()) { - HWND hwndTop = WIN_GetTopParent( msg->hwnd ); - if (hwndTop != GetActiveWindow()) - { - LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, - (WPARAM)hwndTop, - MAKELONG( hittest, msg->message ) ); - if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT)) - eatMsg = TRUE; - if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT)) - { - SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); - WINPOS_ChangeActiveWindow( hwndTop, TRUE ); - } - } + LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop, + MAKELONG( hittest, msg->message ) ); + + if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT)) + eatMsg = TRUE; + + if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT)) + && hwndTop != GetActiveWindow() ) + WINPOS_ChangeActiveWindow( hwndTop, TRUE ); } }