| /* |
| * Outdated !!! |
| * |
| * The edit control is under reconstruction |
| * New documentation will be provided when I'm done |
| * |
| * Please contact me before you send in bug fixes, as the code |
| * might have changed already. However, keep reporting those |
| * bugs ... I might not know about them, yet. |
| * |
| * Frans van Dorsselaer |
| * dorssel@MolPhys.LeidenUniv.nl |
| */ |
| 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 |