|  | /* | 
|  | *	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 |