blob: ec5c4f160f78afd0743b1b477d225079793b18df [file] [log] [blame]
/*
* 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