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. A) basic policy B) special functions C) not implemented / implementation ideas / implementation problems D) known bugs / features A) Basic Policy All messages are handled by EditWndProc(), which is the only external function call. All other functions are static (local to edit.c). All Windows Messages (WM_XXX) are 32-bit, since the edit control is now a 32-bit registered class. The message are dealt with through the helper functions EDIT_WM_XXX(). The edit control messages can be either 16 or 32 bit, depending on the type of application that sends the message. Wherever possible EditWndProc() converts the 16-bit message parameters to parameters corresponding to their 32-bit counterparts. The message is then handled by the appropriate EDIT_EM_XXX() helper function. Sometimes it is not possible to handle the 16-bit and 32-bit versions in the same way, in which case both helper functions EDIT_EM_XXX16() and EDIT_EM_XXX() are defined. All other functions are called EDIT_XXX(). Note: Sometimes a function is internally used a bit different than the specs of a similar function. For instance EDIT_SetSel() is used internally and should not be mixed up with EDIT_EM_SetSel(), a message handler that _does_ conform to the specs of EM_SETSEL. 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. 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. The WND * pointer is used internally whenever possible. Although it is not the real HWND, it improves performance enough to use it. 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.. The text buffer is a kind of tricky. Initially the edit control allocates a HLOCAL32 buffer (32 bit linear memory handler). However, 16 bit application might send a EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF handler). From that moment on we have to keep using this 16 bit memory handler, because it is supposed to be valid at all times after EM_GETHANDLE. What we do is create a HLOCAL16 buffer, copy the text, and do pointer conversion. B) Special functions Several helper functions try to make your life easier when dealing with the allocated buffer. In principle Windows can move memory blocks around unless they are locked. Currently, WINE doesn't do this, but it might in the future. For this reason there is a nice EDIT_GetPointer() function, which locks the heap buffer *only once*, no matter how often it is called. It then returns a nice 32-bit pointer to linear memory. Calling EDIT_GetPointer() is very fast if the buffer is already locked, so you can call it whenever you feel it *might* be useful. At the end of EditWndProc(), EDIT_ReleasePointer() is automatically called which cleans up the initialized pointer. So you don't have to worry about unlocking the memory block. 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), an extra call (besides the cleanup at the end of EditWndProc()) 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_GetPointer(), EDIT_ReleasePointer and EDIT_MakeFit() are aware of the HLOCAL32 / HLOCAL16 business. 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 / Implementation Ideas / Implementation Problems Styles: - ES_CENTER - ES_RIGHT - ES_NUMBER (new since win95) - ES_OEMCONVERT - ES_WANTRETURN None of these should be difficult to include. I just didn't have the time yet. Feel free ... - ES_AUTOVSCROLL (every multi line control *is* auto vscroll) - ES_AUTOHSCROLL (every single line control *is* auto hscroll) (for multi line controls it works : wordwrap) Much, much more difficult. It comes down to this: When there is no autoscrolling, the edit control should first check whether the new text (after a typed key for instance) would fit. If not, an EN_MAXTEXT should be sent. However, currently this would require the actual change to be made, then call EDIT_BuildLineDefs() and then find out that the new text doesn't fit. After all this, things should be put back in the state before the changes. Given the fact that even normal UNDO doesn't work ... Messages: - EM_SETRECT - EM_SETRECTNP - EM_SETMARGINS (new since win95) - EM_FMTLINES These shouldn't be really difficult either. They just confine the visual output to something different than the client rectangle. Currently the client area is used everywhere in the code. At some points this should really be so (GetClientRect32()), whereas at other points it should be the format rectangle (EDIT_EM_GetRect()). Both functions are now used, but inconsistently and mixed up ! If you implement the formatting rectangle / margins, be sure to check all references to RECT's, and how they are / should be obtained. - EM_FMTLINES This means: insert or remove the soft linebreak character (\r\r\n). Probably invented by MS to suit their implementation of the edit control. However, with WINE's implementation I've never come up with occasions where it is actually useful (we never insert \r\r\n, and applications always request removal). If you are a purist ... implementation shouldn't be difficult. Take care to check if the text still fits the buffer after insertion. If not, notify with EN_ERRSPACE. - WM_UNDO (=EM_UNDO) I'm working on it. It is, however, not trivial. Luckily the only function where actual text changes is EM_REPLACESEL, so this is the only spot where we have to worry about UNDO capabilities. Before you try: contact me. I already have ideas and might start implementing it myself really soon. - EM_SETWORDBREAKPROC Not really difficult. It used to work, but since we moved to 32 bits there are now two kinds of callback functions. And I don't know the 32-bit specs for the WordBreakProc() ... Look it up and uncomment the code that is still there for 16 bit callback. - EM_SCROLL Supposed to be the same as WM_VSCROLL, but not quite. In other words: poorly documented. Somebody that knows ? D) Known bugs / Features - The control still calls GetTabbedTextExtent() and TabbedTextOut() in their 16 bit version (since the 32 bit versions don't yet exist). Therefore the tab list is 16 bits (should be 32). - Scrollbar tracking is broken. - Lots of API calls are to 16 bit functions, because their 32 bit versions haven't been implemented yet (e.g. clipboard). - Turning on WordWrap with 16-bit Notepad leaves part of the horizontal scrollbar visible (problem with WM_ERASEBKGND ???). - FIXME's (grep for them). 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