Alexandre Julliard | 889f742 | 1997-04-15 17:19:52 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Outdated !!! |
| 3 | * |
| 4 | * The edit control is under reconstruction |
| 5 | * New documentation will be provided when I'm done |
| 6 | * |
| 7 | * Please contact me before you send in bug fixes, as the code |
| 8 | * might have changed already. However, keep reporting those |
| 9 | * bugs ... I might not know about them, yet. |
| 10 | * |
| 11 | * Frans van Dorsselaer |
| 12 | * dorssel@MolPhys.LeidenUniv.nl |
| 13 | */ |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 14 | This file gives some information about the code in edit.c. If you want to |
| 15 | change, add, or fix code, please read this text. If you're not interested |
| 16 | in doing actual work on edit.c only C & D will be of interest to you. |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 17 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 18 | A) basic policy |
| 19 | B) special functions |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 20 | C) not implemented / implementation ideas / implementation problems |
| 21 | D) known bugs / features |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 22 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 23 | A) Basic Policy |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 24 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 25 | All messages are handled by EditWndProc(), which is the only external |
| 26 | function call. All other functions are static (local to edit.c). |
| 27 | |
| 28 | All Windows Messages (WM_XXX) are 32-bit, since the edit control is now a |
| 29 | 32-bit registered class. The message are dealt with through the helper |
| 30 | functions EDIT_WM_XXX(). |
| 31 | |
| 32 | The edit control messages can be either 16 or 32 bit, depending on the type |
| 33 | of application that sends the message. Wherever possible EditWndProc() |
| 34 | converts the 16-bit message parameters to parameters corresponding to their |
| 35 | 32-bit counterparts. The message is then handled by the appropriate |
| 36 | EDIT_EM_XXX() helper function. Sometimes it is not possible to handle the |
| 37 | 16-bit and 32-bit versions in the same way, in which case both helper |
| 38 | functions EDIT_EM_XXX16() and EDIT_EM_XXX() are defined. |
| 39 | |
| 40 | All other functions are called EDIT_XXX(). |
| 41 | |
| 42 | Note: Sometimes a function is internally used a bit different than the specs |
| 43 | of a similar function. For instance EDIT_SetSel() is used internally and |
| 44 | should not be mixed up with EDIT_EM_SetSel(), a message handler that _does_ |
| 45 | conform to the specs of EM_SETSEL. |
| 46 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 47 | The code has been made in such a way, that functions try to call other |
| 48 | (documented) functions if that is sufficient. This might sometimes not be |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 49 | the most efficient way, but it keeps the code clear. This way I tried to |
| 50 | keep the number of functions that rely on the internal EDITSTATE structure |
| 51 | as low as possible. For instance EDIT_WM_Cut() simply calls EDIT_WM_Copy() |
| 52 | and EDIT_WM_Clear(). The latter two are well documented message handlers, |
| 53 | so as long as they are right EDIT_WM_Cut() will never have to change again. |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 54 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 55 | Example: |
| 56 | The best thing to do, when you want to know the offset of line 3, is calling |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 57 | EDIT_EM_LineIndex(). Again this is a well documented message handler. |
| 58 | Don't look at es->LineDefs[2].offset. It would just be another reference to |
| 59 | the internal structure, and that would make it more difficult to change |
| 60 | things. Refer to EDIT_WM_???? and EDIT_EM_????? functions as much as |
| 61 | possible. |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 62 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 63 | The WND * pointer is used internally whenever possible. Although it is not |
| 64 | the real HWND, it improves performance enough to use it. |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 65 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 66 | All displaying is done by invalidating regions / rects. Only |
| 67 | EDIT_EM_LineScroll() uses direct painting. This way things become much |
| 68 | faster. Although sometimes the response time might appear to be slow, it |
| 69 | would be much slower even, when everything would be painted instantly. This |
| 70 | is especially true for scrollbar tracking and selection changes.. |
Alexandre Julliard | 22945d5 | 1995-03-02 17:44:29 +0000 | [diff] [blame] | 71 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 72 | The text buffer is a kind of tricky. Initially the edit control allocates a |
| 73 | HLOCAL32 buffer (32 bit linear memory handler). However, 16 bit application |
| 74 | might send a EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF |
| 75 | handler). From that moment on we have to keep using this 16 bit memory |
| 76 | handler, because it is supposed to be valid at all times after EM_GETHANDLE. |
| 77 | What we do is create a HLOCAL16 buffer, copy the text, and do pointer |
| 78 | conversion. |
| 79 | |
Alexandre Julliard | d2e1c1a | 1996-03-09 16:12:43 +0000 | [diff] [blame] | 80 | |
Alexandre Julliard | d2e1c1a | 1996-03-09 16:12:43 +0000 | [diff] [blame] | 81 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 82 | B) Special functions |
Alexandre Julliard | d2e1c1a | 1996-03-09 16:12:43 +0000 | [diff] [blame] | 83 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 84 | Several helper functions try to make your life easier when dealing with the |
| 85 | allocated buffer. In principle Windows can move memory blocks around unless |
| 86 | they are locked. Currently, WINE doesn't do this, but it might in the |
| 87 | future. |
| 88 | |
| 89 | For this reason there is a nice EDIT_GetPointer() function, which locks the |
| 90 | heap buffer *only once*, no matter how often it is called. It then returns a |
| 91 | nice 32-bit pointer to linear memory. Calling EDIT_GetPointer() is very fast |
| 92 | if the buffer is already locked, so you can call it whenever you feel it |
| 93 | *might* be useful. |
| 94 | |
| 95 | At the end of EditWndProc(), EDIT_ReleasePointer() is automatically called |
| 96 | which cleans up the initialized pointer. So you don't have to worry about |
| 97 | unlocking the memory block. This way, the buffer gets locked / unlock only |
| 98 | once every message, although EDIT_GetPointer() may actually have been called |
| 99 | a hundred times. Only when the actual HLOCAL is needed (for example to |
| 100 | ReAlloc), an extra call (besides the cleanup at the end of EditWndProc()) to |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 101 | EDIT_ReleasePointer() is needed. Look for instance in EDIT_MakeFit(). |
| 102 | |
| 103 | This brings us to EDIT_MakeFit(). It automatically re-allocates the buffer |
| 104 | if the size parameter > buffersize. If everything is successful TRUE is |
| 105 | returned, otherwise FALSE. Only when the buffer contents may grow you need |
| 106 | to call EDIT_MakeFit(). Currently this is only in EDIT_ReplaceSel() and |
| 107 | EDIT_WM_SetText(). |
| 108 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 109 | EDIT_GetPointer(), EDIT_ReleasePointer and EDIT_MakeFit() are aware of the |
| 110 | HLOCAL32 / HLOCAL16 business. |
| 111 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 112 | EDIT_BuildLineDefs() is the most important function in edit.c. It builds |
| 113 | the internal EDITSTATE structure. As soon as text *might* have changed, or |
| 114 | when the appearance of the text on the screen *might* have changed, call |
| 115 | this function ! This includes changes of screen size, change of the font, |
| 116 | clipboard actions, etc. etc. Most other functions that rely on EDITSTATE, |
| 117 | rely on the stuff this function builds. |
| 118 | |
| 119 | |
| 120 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 121 | C) Not Implemented / Implementation Ideas / Implementation Problems |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 122 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 123 | Styles: |
| 124 | |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 125 | - ES_CENTER |
| 126 | - ES_RIGHT |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 127 | - ES_NUMBER (new since win95) |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 128 | - ES_OEMCONVERT |
| 129 | - ES_WANTRETURN |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 130 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 131 | None of these should be difficult to include. I just didn't have the time |
| 132 | yet. Feel free ... |
| 133 | |
| 134 | - ES_AUTOVSCROLL (every multi line control *is* auto vscroll) |
| 135 | - ES_AUTOHSCROLL (every single line control *is* auto hscroll) |
| 136 | (for multi line controls it works : wordwrap) |
| 137 | |
| 138 | Much, much more difficult. It comes down to this: When there is no |
| 139 | autoscrolling, the edit control should first check whether the new text |
| 140 | (after a typed key for instance) would fit. If not, an EN_MAXTEXT should be |
| 141 | sent. However, currently this would require the actual change to be made, |
| 142 | then call EDIT_BuildLineDefs() and then find out that the new text doesn't |
| 143 | fit. After all this, things should be put back in the state before the |
| 144 | changes. Given the fact that even normal UNDO doesn't work ... |
| 145 | |
| 146 | Messages: |
| 147 | |
| 148 | - EM_SETRECT |
| 149 | - EM_SETRECTNP |
| 150 | - EM_SETMARGINS (new since win95) |
| 151 | - EM_FMTLINES |
| 152 | |
| 153 | These shouldn't be really difficult either. They just confine the visual |
| 154 | output to something different than the client rectangle. Currently the |
| 155 | client area is used everywhere in the code. At some points this should |
| 156 | really be so (GetClientRect32()), whereas at other points it should be the |
| 157 | format rectangle (EDIT_EM_GetRect()). Both functions are now used, but |
| 158 | inconsistently and mixed up ! If you implement the formatting rectangle / |
| 159 | margins, be sure to check all references to RECT's, and how they are / |
| 160 | should be obtained. |
| 161 | |
| 162 | - EM_FMTLINES |
| 163 | |
| 164 | This means: insert or remove the soft linebreak character (\r\r\n). Probably |
| 165 | invented by MS to suit their implementation of the edit control. However, |
| 166 | with WINE's implementation I've never come up with occasions where it is |
| 167 | actually useful (we never insert \r\r\n, and applications always request |
| 168 | removal). If you are a purist ... implementation shouldn't be difficult. |
| 169 | Take care to check if the text still fits the buffer after insertion. If |
| 170 | not, notify with EN_ERRSPACE. |
| 171 | |
| 172 | - WM_UNDO (=EM_UNDO) |
| 173 | |
| 174 | I'm working on it. It is, however, not trivial. Luckily the only function |
| 175 | where actual text changes is EM_REPLACESEL, so this is the only spot where |
| 176 | we have to worry about UNDO capabilities. Before you try: contact me. I |
| 177 | already have ideas and might start implementing it myself really soon. |
| 178 | |
| 179 | - EM_SETWORDBREAKPROC |
| 180 | |
| 181 | Not really difficult. It used to work, but since we moved to 32 bits there |
| 182 | are now two kinds of callback functions. And I don't know the 32-bit specs |
| 183 | for the WordBreakProc() ... Look it up and uncomment the code that is still |
| 184 | there for 16 bit callback. |
| 185 | |
| 186 | - EM_SCROLL |
| 187 | |
| 188 | Supposed to be the same as WM_VSCROLL, but not quite. In other words: |
| 189 | poorly documented. Somebody that knows ? |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 190 | |
| 191 | |
| 192 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 193 | D) Known bugs / Features |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 194 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 195 | - The control still calls GetTabbedTextExtent() and TabbedTextOut() in |
| 196 | their 16 bit version (since the 32 bit versions don't yet exist). |
| 197 | Therefore the tab list is 16 bits (should be 32). |
| 198 | - Scrollbar tracking is broken. |
| 199 | - Lots of API calls are to 16 bit functions, because their 32 bit |
| 200 | versions haven't been implemented yet (e.g. clipboard). |
| 201 | - Turning on WordWrap with 16-bit Notepad leaves part of the horizontal |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 202 | scrollbar visible (problem with WM_ERASEBKGND ???). |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 203 | - FIXME's (grep for them). |
Alexandre Julliard | 329f068 | 1996-04-14 13:21:20 +0000 | [diff] [blame] | 204 | |
| 205 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 206 | I am working on Undo capabilities. If you want to do things, other than bug |
| 207 | fixes, please mail me so we can synchronize. |
Alexandre Julliard | d2e1c1a | 1996-03-09 16:12:43 +0000 | [diff] [blame] | 208 | |
| 209 | Frans van Dorsselaer |
| 210 | dorssel@rulhm1.LeidenUniv.nl |