Ignore:
Timestamp:
Jul 31, 2003, 6:07:57 PM (22 years ago)
Author:
sandervl
Message:

KOMH: DBCS updates/fixes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/user32/edit.c

    r9760 r10195  
    11/*
    2  *      Edit control
    3  *
    4  *      Copyright  David W. Metcalfe, 1994
    5  *      Copyright  William Magro, 1995, 1996
    6  *      Copyright  Frans van Dorsselaer, 1996, 1997
     2 *  Edit control
     3 *
     4 *  Copyright  David W. Metcalfe, 1994
     5 *  Copyright  William Magro, 1995, 1996
     6 *  Copyright  Frans van Dorsselaer, 1996, 1997
    77 *
    88 */
    99
    1010/*
    11  *      please read EDIT.TODO (and update it when you change things)
     11 *  please read EDIT.TODO (and update it when you change things)
    1212 */
    1313
     
    3030#ifdef __WIN32OS2__
    3131#include "ctrlconf.h"
     32#include <heapstring.h>
    3233#endif
    3334
     
    3738DECLARE_DEBUG_CHANNEL(relay);
    3839
    39 #define BUFLIMIT_MULTI          0x7FFFFFF       /* maximum buffer size (not including '\0')
    40 #define BUFLIMIT_SINGLE         0x7FFFFFF       /* maximum buffer size (not including '\0') */
     40#define BUFLIMIT_MULTI      0x7FFFFFF   /* maximum buffer size (not including '\0')
     41#define BUFLIMIT_SINGLE     0x7FFFFFF   /* maximum buffer size (not including '\0') */
    4142#else
    42 #define BUFLIMIT_MULTI          65534   /* maximum buffer size (not including '\0')
    43                                            FIXME: BTW, new specs say 65535 (do you dare ???) */
    44 #define BUFLIMIT_SINGLE         32766   /* maximum buffer size (not including '\0') */
     43#define BUFLIMIT_MULTI      65534   /* maximum buffer size (not including '\0')
     44                       FIXME: BTW, new specs say 65535 (do you dare ???) */
     45#define BUFLIMIT_SINGLE     32766   /* maximum buffer size (not including '\0') */
    4546#endif
    4647
    47 #define GROWLENGTH              32      /* buffers granularity in bytes: must be power of 2 */
    48 #define ROUND_TO_GROW(size)     (((size) + (GROWLENGTH - 1)) & ~(GROWLENGTH - 1))
    49 #define HSCROLL_FRACTION        3       /* scroll window by 1/3 width */
     48#define GROWLENGTH      32  /* buffers granularity in bytes: must be power of 2 */
     49#define ROUND_TO_GROW(size) (((size) + (GROWLENGTH - 1)) & ~(GROWLENGTH - 1))
     50#define HSCROLL_FRACTION    3   /* scroll window by 1/3 width */
    5051
    5152/*
    52  *      extra flags for EDITSTATE.flags field
    53  */
    54 #define EF_MODIFIED             0x0001  /* text has been modified */
    55 #define EF_FOCUSED              0x0002  /* we have input focus */
    56 #define EF_UPDATE               0x0004  /* notify parent of changed state */
    57 #define EF_VSCROLL_TRACK        0x0008  /* don't SetScrollPos() since we are tracking the thumb */
    58 #define EF_HSCROLL_TRACK        0x0010  /* don't SetScrollPos() since we are tracking the thumb */
    59 #define EF_AFTER_WRAP           0x0080  /* the caret is displayed after the last character of a
    60                                            wrapped line, instead of in front of the next character */
    61 #define EF_USE_SOFTBRK          0x0100  /* Enable soft breaks in text. */
     53 *  extra flags for EDITSTATE.flags field
     54 */
     55#define EF_MODIFIED     0x0001  /* text has been modified */
     56#define EF_FOCUSED      0x0002  /* we have input focus */
     57#define EF_UPDATE       0x0004  /* notify parent of changed state */
     58#define EF_VSCROLL_TRACK    0x0008  /* don't SetScrollPos() since we are tracking the thumb */
     59#define EF_HSCROLL_TRACK    0x0010  /* don't SetScrollPos() since we are tracking the thumb */
     60#define EF_AFTER_WRAP       0x0080  /* the caret is displayed after the last character of a
     61                       wrapped line, instead of in front of the next character */
     62#define EF_USE_SOFTBRK      0x0100  /* Enable soft breaks in text. */
    6263
    6364typedef enum
    6465{
    65         END_0 = 0,      /* line ends with terminating '\0' character */
    66         END_WRAP,       /* line is wrapped */
    67         END_HARD,       /* line ends with a hard return '\r\n' */
    68         END_SOFT        /* line ends with a soft return '\r\r\n' */
     66    END_0 = 0,  /* line ends with terminating '\0' character */
     67    END_WRAP,   /* line is wrapped */
     68    END_HARD,   /* line ends with a hard return '\r\n' */
     69    END_SOFT    /* line ends with a soft return '\r\r\n' */
    6970} LINE_END;
    7071
    7172typedef struct tagLINEDEF {
    72         INT length;             /* bruto length of a line in bytes */
    73         INT net_length; /* netto length of a line in visible characters */
    74         LINE_END ending;
    75         INT width;              /* width of the line in pixels */
    76         INT index; /* line index into the buffer */
    77         struct tagLINEDEF *next;
     73    INT length;     /* bruto length of a line in bytes */
     74    INT net_length; /* netto length of a line in visible characters */
     75    LINE_END ending;
     76    INT width;      /* width of the line in pixels */
     77    INT index; /* line index into the buffer */
     78    struct tagLINEDEF *next;
    7879} LINEDEF;
    7980
    8081typedef struct
    8182{
    82         BOOL is_unicode;                /* how the control was created */
    83         LPWSTR text;                    /* the actual contents of the control */
    84         UINT buffer_size;               /* the size of the buffer in characters */
    85         UINT buffer_limit;              /* the maximum size to which the buffer may grow in characters */
    86         HFONT font;                     /* NULL means standard system font */
    87         INT x_offset;                   /* scroll offset        for multi lines this is in pixels
    88                                                                 for single lines it's in characters */
    89         INT line_height;                /* height of a screen line in pixels */
    90         INT char_width;         /* average character width in pixels */
    91         DWORD style;                    /* sane version of wnd->dwStyle */
    92         WORD flags;                     /* flags that are not in es->style or wnd->flags (EF_XXX) */
    93         INT undo_insert_count;  /* number of characters inserted in sequence */
    94         UINT undo_position;             /* character index of the insertion and deletion */
    95         LPWSTR undo_text;               /* deleted text */
    96         UINT undo_buffer_size;          /* size of the deleted text buffer */
    97         INT selection_start;            /* == selection_end if no selection */
    98         INT selection_end;              /* == current caret position */
    99         WCHAR password_char;            /* == 0 if no password char, and for multi line controls */
    100         INT left_margin;                /* in pixels */
    101         INT right_margin;               /* in pixels */
    102         RECT format_rect;
    103         INT text_width;                 /* width of the widest line in pixels for multi line controls
    104                                            and just line width for single line controls */
    105         INT region_posx;                /* Position of cursor relative to region: */
    106         INT region_posy;                /* -1: to left, 0: within, 1: to right */
    107         EDITWORDBREAKPROC16 word_break_proc16;
    108         void *word_break_proc;          /* 32-bit word break proc: ANSI or Unicode */
    109         INT line_count;         /* number of lines */
    110         INT y_offset;                   /* scroll offset in number of lines */
    111         BOOL bCaptureState; /* flag indicating whether mouse was captured */
    112         BOOL bEnableState;             /* flag keeping the enable state */
    113         HWND hwndParent;               /* Handle of parent for sending EN_* messages.
    114                                           Even if parent will change, EN_* messages
    115                                           should be sent to the first parent. */
    116         HWND hwndListBox;              /* handle of ComboBox's listbox or NULL */
    117         /*
    118          *      only for multi line controls
    119         */
    120         INT lock_count;         /* amount of re-entries in the EditWndProc */
    121         INT tabs_count;
    122         LPINT tabs;
    123         LINEDEF *first_line_def;        /* linked list of (soft) linebreaks */
    124         HLOCAL hloc32W;         /* our unicode local memory block */
    125         HLOCAL16 hloc16;        /* alias for 16-bit control receiving EM_GETHANDLE16
    126                                    or EM_SETHANDLE16 */
    127         HLOCAL hloc32A;         /* alias for ANSI control receiving EM_GETHANDLE
    128                                    or EM_SETHANDLE */
     83    BOOL is_unicode;        /* how the control was created */
     84    LPWSTR text;            /* the actual contents of the control */
     85    UINT buffer_size;       /* the size of the buffer in characters */
     86    UINT buffer_limit;      /* the maximum size to which the buffer may grow in characters */
     87    HFONT font;         /* NULL means standard system font */
     88    INT x_offset;           /* scroll offset    for multi lines this is in pixels
     89                                for single lines it's in characters */
     90    INT line_height;        /* height of a screen line in pixels */
     91    INT char_width;     /* average character width in pixels */
     92    DWORD style;            /* sane version of wnd->dwStyle */
     93    WORD flags;         /* flags that are not in es->style or wnd->flags (EF_XXX) */
     94    INT undo_insert_count;  /* number of characters inserted in sequence */
     95    UINT undo_position;     /* character index of the insertion and deletion */
     96    LPWSTR undo_text;       /* deleted text */
     97    UINT undo_buffer_size;      /* size of the deleted text buffer */
     98    INT selection_start;        /* == selection_end if no selection */
     99    INT selection_end;      /* == current caret position */
     100    WCHAR password_char;        /* == 0 if no password char, and for multi line controls */
     101    INT left_margin;        /* in pixels */
     102    INT right_margin;       /* in pixels */
     103    RECT format_rect;
     104    INT text_width;         /* width of the widest line in pixels for multi line controls
     105                       and just line width for single line controls */
     106    INT region_posx;        /* Position of cursor relative to region: */
     107    INT region_posy;        /* -1: to left, 0: within, 1: to right */
     108    EDITWORDBREAKPROC16 word_break_proc16;
     109    void *word_break_proc;      /* 32-bit word break proc: ANSI or Unicode */
     110    INT line_count;     /* number of lines */
     111    INT y_offset;           /* scroll offset in number of lines */
     112    BOOL bCaptureState; /* flag indicating whether mouse was captured */
     113    BOOL bEnableState;             /* flag keeping the enable state */
     114    HWND hwndParent;               /* Handle of parent for sending EN_* messages.
     115                          Even if parent will change, EN_* messages
     116                      should be sent to the first parent. */
     117    HWND hwndListBox;              /* handle of ComboBox's listbox or NULL */
     118    /*
     119     *  only for multi line controls
     120    */
     121    INT lock_count;     /* amount of re-entries in the EditWndProc */
     122    INT tabs_count;
     123    LPINT tabs;
     124    LINEDEF *first_line_def;    /* linked list of (soft) linebreaks */
     125    HLOCAL hloc32W;     /* our unicode local memory block */
     126    HLOCAL16 hloc16;    /* alias for 16-bit control receiving EM_GETHANDLE16
     127                   or EM_SETHANDLE16 */
     128    HLOCAL hloc32A;     /* alias for ANSI control receiving EM_GETHANDLE
     129                   or EM_SETHANDLE */
    129130} EDITSTATE;
    130131
     
    137138
    138139#define DPRINTF_EDIT_NOTIFY(hwnd, str) \
    139         do {TRACE("notification " str " sent to hwnd=%08x\n", \
    140                        (UINT)(hwnd));} while(0)
     140    do {TRACE("notification " str " sent to hwnd=%08x\n", \
     141               (UINT)(hwnd));} while(0)
    141142
    142143/* used for disabled or read-only edit control */
    143144#define EDIT_SEND_CTLCOLORSTATIC(hwnd,hdc) \
    144         (SendMessageW(GetParent(hwnd), WM_CTLCOLORSTATIC, \
    145                         (WPARAM)(hdc), (LPARAM)(hwnd)))
     145    (SendMessageW(GetParent(hwnd), WM_CTLCOLORSTATIC, \
     146            (WPARAM)(hdc), (LPARAM)(hwnd)))
    146147#define EDIT_SEND_CTLCOLOR(hwnd,hdc) \
    147         (SendMessageW(GetParent(hwnd), WM_CTLCOLOREDIT, \
    148                         (WPARAM)(hdc), (LPARAM)(hwnd)))
     148    (SendMessageW(GetParent(hwnd), WM_CTLCOLOREDIT, \
     149            (WPARAM)(hdc), (LPARAM)(hwnd)))
    149150#define EDIT_NOTIFY_PARENT(hwnd, es, wNotifyCode, str) \
    150         do \
    151         { /* Notify parent which has created this edit control */ \
    152             DPRINTF_EDIT_NOTIFY((es)->hwndParent, str); \
    153             SendMessageW((es)->hwndParent, WM_COMMAND, \
    154                      MAKEWPARAM(GetWindowLongA((hwnd),GWL_ID), wNotifyCode), \
    155                      (LPARAM)(hwnd)); \
    156         } while(0)
     151    do \
     152    { /* Notify parent which has created this edit control */ \
     153        DPRINTF_EDIT_NOTIFY((es)->hwndParent, str); \
     154        SendMessageW((es)->hwndParent, WM_COMMAND, \
     155             MAKEWPARAM(GetWindowLongA((hwnd),GWL_ID), wNotifyCode), \
     156             (LPARAM)(hwnd)); \
     157    } while(0)
    157158#define DPRINTF_EDIT_MSG16(str) \
    158         TRACE(\
    159                      "16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
    160                      hwnd, (UINT)wParam, (UINT)lParam)
     159    TRACE(\
     160             "16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
     161             hwnd, (UINT)wParam, (UINT)lParam)
    161162#define DPRINTF_EDIT_MSG32(str) \
    162         TRACE(\
    163                      "32 bit %c : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
    164                      unicode ? 'W' : 'A', \
    165                      hwnd, (UINT)wParam, (UINT)lParam)
    166 
    167 /*********************************************************************
    168  *
    169  *      Declarations
     163    TRACE(\
     164             "32 bit %c : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
     165             unicode ? 'W' : 'A', \
     166             hwnd, (UINT)wParam, (UINT)lParam)
     167
     168/*********************************************************************
     169 *
     170 *  Declarations
    170171 *
    171172 */
    172173
    173174/*
    174  *      These functions have trivial implementations
    175  *      We still like to call them internally
    176  *      "static inline" makes them more like macro's
    177  */
    178 static inline BOOL      EDIT_EM_CanUndo(EDITSTATE *es);
    179 static inline void      EDIT_EM_EmptyUndoBuffer(EDITSTATE *es);
    180 static inline void      EDIT_WM_Clear(HWND hwnd, EDITSTATE *es);
    181 static inline void      EDIT_WM_Cut(HWND hwnd, EDITSTATE *es);
     175 *  These functions have trivial implementations
     176 *  We still like to call them internally
     177 *  "static inline" makes them more like macro's
     178 */
     179static inline BOOL  EDIT_EM_CanUndo(EDITSTATE *es);
     180static inline void  EDIT_EM_EmptyUndoBuffer(EDITSTATE *es);
     181static inline void  EDIT_WM_Clear(HWND hwnd, EDITSTATE *es);
     182static inline void  EDIT_WM_Cut(HWND hwnd, EDITSTATE *es);
    182183
    183184/*
    184  *      Helper functions only valid for one type of control
    185  */
    186 static void     EDIT_BuildLineDefs_ML(HWND hwnd, EDITSTATE *es, INT iStart, INT iEnd, INT delta, HRGN hrgn);
    187 static void     EDIT_CalcLineWidth_SL(HWND hwnd, EDITSTATE *es);
    188 static LPWSTR   EDIT_GetPasswordPointer_SL(EDITSTATE *es);
    189 static void     EDIT_MoveDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
    190 static void     EDIT_MovePageDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
    191 static void     EDIT_MovePageUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
    192 static void     EDIT_MoveUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
     185 *  Helper functions only valid for one type of control
     186 */
     187static void EDIT_BuildLineDefs_ML(HWND hwnd, EDITSTATE *es, INT iStart, INT iEnd, INT delta, HRGN hrgn);
     188static void EDIT_CalcLineWidth_SL(HWND hwnd, EDITSTATE *es);
     189static LPWSTR   EDIT_GetPasswordPointer_SL(EDITSTATE *es);
     190static void EDIT_MoveDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
     191static void EDIT_MovePageDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
     192static void EDIT_MovePageUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
     193static void EDIT_MoveUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
    193194/*
    194  *      Helper functions valid for both single line _and_ multi line controls
    195  */
    196 static INT      EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action);
    197 static INT      EDIT_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap);
    198 static void     EDIT_ConfinePoint(EDITSTATE *es, LPINT x, LPINT y);
    199 static void     EDIT_GetLineRect(HWND hwnd, EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc);
    200 static void     EDIT_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end);
    201 static void     EDIT_LockBuffer(HWND hwnd, EDITSTATE *es);
    202 static BOOL     EDIT_MakeFit(HWND hwnd, EDITSTATE *es, UINT size);
    203 static BOOL     EDIT_MakeUndoFit(EDITSTATE *es, UINT size);
    204 static void     EDIT_MoveBackward(HWND hwnd, EDITSTATE *es, BOOL extend);
    205 static void     EDIT_MoveEnd(HWND hwnd, EDITSTATE *es, BOOL extend);
    206 static void     EDIT_MoveForward(HWND hwnd, EDITSTATE *es, BOOL extend);
    207 static void     EDIT_MoveHome(HWND hwnd, EDITSTATE *es, BOOL extend);
    208 static void     EDIT_MoveWordBackward(HWND hwnd, EDITSTATE *es, BOOL extend);
    209 static void     EDIT_MoveWordForward(HWND hwnd, EDITSTATE *es, BOOL extend);
    210 static void     EDIT_PaintLine(HWND hwnd, EDITSTATE *es, HDC hdc, INT line, BOOL rev);
    211 static INT      EDIT_PaintText(EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
    212 static void     EDIT_SetCaretPos(HWND hwnd, EDITSTATE *es, INT pos, BOOL after_wrap);
    213 static void     EDIT_SetRectNP(HWND hwnd, EDITSTATE *es, LPRECT lprc);
    214 static void     EDIT_UnlockBuffer(HWND hwnd, EDITSTATE *es, BOOL force);
    215 static void     EDIT_UpdateScrollInfo(HWND hwnd, EDITSTATE *es);
     195 *  Helper functions valid for both single line _and_ multi line controls
     196 */
     197static INT  EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action);
     198static INT  EDIT_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap);
     199static void EDIT_ConfinePoint(EDITSTATE *es, LPINT x, LPINT y);
     200static void EDIT_GetLineRect(HWND hwnd, EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc);
     201static void EDIT_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end);
     202static void EDIT_LockBuffer(HWND hwnd, EDITSTATE *es);
     203static BOOL EDIT_MakeFit(HWND hwnd, EDITSTATE *es, UINT size);
     204static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size);
     205static void EDIT_MoveBackward(HWND hwnd, EDITSTATE *es, BOOL extend);
     206static void EDIT_MoveEnd(HWND hwnd, EDITSTATE *es, BOOL extend);
     207static void EDIT_MoveForward(HWND hwnd, EDITSTATE *es, BOOL extend);
     208static void EDIT_MoveHome(HWND hwnd, EDITSTATE *es, BOOL extend);
     209static void EDIT_MoveWordBackward(HWND hwnd, EDITSTATE *es, BOOL extend);
     210static void EDIT_MoveWordForward(HWND hwnd, EDITSTATE *es, BOOL extend);
     211static void EDIT_PaintLine(HWND hwnd, EDITSTATE *es, HDC hdc, INT line, BOOL rev);
     212static INT  EDIT_PaintText(EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
     213static void EDIT_SetCaretPos(HWND hwnd, EDITSTATE *es, INT pos, BOOL after_wrap);
     214static void EDIT_SetRectNP(HWND hwnd, EDITSTATE *es, LPRECT lprc);
     215static void EDIT_UnlockBuffer(HWND hwnd, EDITSTATE *es, BOOL force);
     216static void EDIT_UpdateScrollInfo(HWND hwnd, EDITSTATE *es);
    216217static INT CALLBACK EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action);
    217218/*
    218  *      EM_XXX message handlers
    219  */
    220 static LRESULT  EDIT_EM_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y);
    221 static BOOL     EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol);
    222 static HLOCAL   EDIT_EM_GetHandle(EDITSTATE *es);
     219 *  EM_XXX message handlers
     220 */
     221static LRESULT  EDIT_EM_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y);
     222static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol);
     223static HLOCAL   EDIT_EM_GetHandle(EDITSTATE *es);
    223224#ifndef __WIN32OS2__
    224 static HLOCAL16 EDIT_EM_GetHandle16(HWND hwnd, EDITSTATE *es);
     225static HLOCAL16 EDIT_EM_GetHandle16(HWND hwnd, EDITSTATE *es);
    225226#endif
    226 static INT      EDIT_EM_GetLine(EDITSTATE *es, INT line, LPARAM lParam, BOOL unicode);
    227 static LRESULT  EDIT_EM_GetSel(EDITSTATE *es, LPUINT start, LPUINT end);
    228 static LRESULT  EDIT_EM_GetThumb(HWND hwnd, EDITSTATE *es);
    229 static INT      EDIT_EM_LineFromChar(EDITSTATE *es, INT index);
    230 static INT      EDIT_EM_LineIndex(EDITSTATE *es, INT line);
    231 static INT      EDIT_EM_LineLength(EDITSTATE *es, INT index);
    232 static BOOL     EDIT_EM_LineScroll(HWND hwnd, EDITSTATE *es, INT dx, INT dy);
    233 static BOOL     EDIT_EM_LineScroll_internal(HWND hwnd, EDITSTATE *es, INT dx, INT dy);
    234 static LRESULT  EDIT_EM_PosFromChar(HWND hwnd, EDITSTATE *es, INT index, BOOL after_wrap);
    235 static void     EDIT_EM_ReplaceSel(HWND hwnd, EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update);
    236 static LRESULT  EDIT_EM_Scroll(HWND hwnd, EDITSTATE *es, INT action);
    237 static void     EDIT_EM_ScrollCaret(HWND hwnd, EDITSTATE *es);
    238 static void     EDIT_EM_SetHandle(HWND hwnd, EDITSTATE *es, HLOCAL hloc);
     227static INT  EDIT_EM_GetLine(EDITSTATE *es, INT line, LPARAM lParam, BOOL unicode);
     228static LRESULT  EDIT_EM_GetSel(EDITSTATE *es, LPUINT start, LPUINT end);
     229static LRESULT  EDIT_EM_GetThumb(HWND hwnd, EDITSTATE *es);
     230static INT  EDIT_EM_LineFromChar(EDITSTATE *es, INT index);
     231static INT  EDIT_EM_LineIndex(EDITSTATE *es, INT line);
     232static INT  EDIT_EM_LineLength(EDITSTATE *es, INT index);
     233static BOOL EDIT_EM_LineScroll(HWND hwnd, EDITSTATE *es, INT dx, INT dy);
     234static BOOL EDIT_EM_LineScroll_internal(HWND hwnd, EDITSTATE *es, INT dx, INT dy);
     235static LRESULT  EDIT_EM_PosFromChar(HWND hwnd, EDITSTATE *es, INT index, BOOL after_wrap);
     236static void EDIT_EM_ReplaceSel(HWND hwnd, EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update);
     237static LRESULT  EDIT_EM_Scroll(HWND hwnd, EDITSTATE *es, INT action);
     238static void EDIT_EM_ScrollCaret(HWND hwnd, EDITSTATE *es);
     239static void EDIT_EM_SetHandle(HWND hwnd, EDITSTATE *es, HLOCAL hloc);
    239240#ifndef __WIN32OS2__
    240 static void     EDIT_EM_SetHandle16(HWND hwnd, EDITSTATE *es, HLOCAL16 hloc);
     241static void EDIT_EM_SetHandle16(HWND hwnd, EDITSTATE *es, HLOCAL16 hloc);
    241242#endif
    242 static void     EDIT_EM_SetLimitText(EDITSTATE *es, INT limit);
    243 static void     EDIT_EM_SetMargins(EDITSTATE *es, INT action, INT left, INT right);
    244 static void     EDIT_EM_SetPasswordChar(HWND hwnd, EDITSTATE *es, WCHAR c);
    245 static void     EDIT_EM_SetSel(HWND hwnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
    246 static BOOL     EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs);
    247 static BOOL     EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs);
    248 static void     EDIT_EM_SetWordBreakProc(HWND hwnd, EDITSTATE *es, LPARAM lParam);
     243static void EDIT_EM_SetLimitText(EDITSTATE *es, INT limit);
     244static void EDIT_EM_SetMargins(EDITSTATE *es, INT action, INT left, INT right);
     245static void EDIT_EM_SetPasswordChar(HWND hwnd, EDITSTATE *es, WCHAR c);
     246static void EDIT_EM_SetSel(HWND hwnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
     247static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs);
     248static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs);
     249static void EDIT_EM_SetWordBreakProc(HWND hwnd, EDITSTATE *es, LPARAM lParam);
    249250#ifndef __WIN32OS2__
    250 static void     EDIT_EM_SetWordBreakProc16(HWND hwnd, EDITSTATE *es, EDITWORDBREAKPROC16 wbp);
     251static void EDIT_EM_SetWordBreakProc16(HWND hwnd, EDITSTATE *es, EDITWORDBREAKPROC16 wbp);
    251252#endif
    252 static BOOL     EDIT_EM_Undo(HWND hwnd, EDITSTATE *es);
     253static BOOL EDIT_EM_Undo(HWND hwnd, EDITSTATE *es);
    253254/*
    254  *      WM_XXX message handlers
    255  */
    256 static void     EDIT_WM_Char(HWND hwnd, EDITSTATE *es, WCHAR c);
    257 static void     EDIT_WM_Command(HWND hwnd, EDITSTATE *es, INT code, INT id, HWND conrtol);
    258 static void     EDIT_WM_ContextMenu(HWND hwnd, EDITSTATE *es, INT x, INT y);
    259 static void     EDIT_WM_Copy(HWND hwnd, EDITSTATE *es);
    260 static LRESULT  EDIT_WM_Create(HWND hwnd, EDITSTATE *es, LPCWSTR name);
    261 static void     EDIT_WM_Destroy(HWND hwnd, EDITSTATE *es);
    262 static LRESULT  EDIT_WM_EraseBkGnd(HWND hwnd, EDITSTATE *es, HDC dc);
    263 static INT      EDIT_WM_GetText(EDITSTATE *es, INT count, LPARAM lParam, BOOL unicode);
    264 static LRESULT  EDIT_WM_HScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos);
    265 static LRESULT  EDIT_WM_KeyDown(HWND hwnd, EDITSTATE *es, INT key);
    266 static LRESULT  EDIT_WM_KillFocus(HWND hwnd, EDITSTATE *es);
    267 static LRESULT  EDIT_WM_LButtonDblClk(HWND hwnd, EDITSTATE *es);
    268 static LRESULT  EDIT_WM_LButtonDown(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y);
    269 static LRESULT  EDIT_WM_LButtonUp(HWND hwndSelf, EDITSTATE *es);
    270 static LRESULT  EDIT_WM_MButtonDown(HWND hwnd);
    271 static LRESULT  EDIT_WM_MouseMove(HWND hwnd, EDITSTATE *es, INT x, INT y);
    272 static LRESULT  EDIT_WM_NCCreate(HWND hwnd, DWORD style, HWND hwndParent, BOOL unicode);
    273 static void     EDIT_WM_Paint(HWND hwnd, EDITSTATE *es, WPARAM wParam);
    274 static void     EDIT_WM_Paste(HWND hwnd, EDITSTATE *es);
    275 static void     EDIT_WM_SetFocus(HWND hwnd, EDITSTATE *es);
    276 static void     EDIT_WM_SetFont(HWND hwnd, EDITSTATE *es, HFONT font, BOOL redraw);
    277 static void     EDIT_WM_SetText(HWND hwnd, EDITSTATE *es, LPARAM lParam, BOOL unicode);
    278 static void     EDIT_WM_Size(HWND hwnd, EDITSTATE *es, UINT action, INT width, INT height);
     255 *  WM_XXX message handlers
     256 */
     257static void EDIT_WM_Char(HWND hwnd, EDITSTATE *es, WCHAR c);
     258static void EDIT_WM_Command(HWND hwnd, EDITSTATE *es, INT code, INT id, HWND conrtol);
     259static void EDIT_WM_ContextMenu(HWND hwnd, EDITSTATE *es, INT x, INT y);
     260static void EDIT_WM_Copy(HWND hwnd, EDITSTATE *es);
     261static LRESULT  EDIT_WM_Create(HWND hwnd, EDITSTATE *es, LPCWSTR name);
     262static void EDIT_WM_Destroy(HWND hwnd, EDITSTATE *es);
     263static LRESULT  EDIT_WM_EraseBkGnd(HWND hwnd, EDITSTATE *es, HDC dc);
     264static INT  EDIT_WM_GetText(EDITSTATE *es, INT count, LPARAM lParam, BOOL unicode);
     265static LRESULT  EDIT_WM_HScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos);
     266static LRESULT  EDIT_WM_KeyDown(HWND hwnd, EDITSTATE *es, INT key);
     267static LRESULT  EDIT_WM_KillFocus(HWND hwnd, EDITSTATE *es);
     268static LRESULT  EDIT_WM_LButtonDblClk(HWND hwnd, EDITSTATE *es);
     269static LRESULT  EDIT_WM_LButtonDown(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y);
     270static LRESULT  EDIT_WM_LButtonUp(HWND hwndSelf, EDITSTATE *es);
     271static LRESULT  EDIT_WM_MButtonDown(HWND hwnd);
     272static LRESULT  EDIT_WM_MouseMove(HWND hwnd, EDITSTATE *es, INT x, INT y);
     273static LRESULT  EDIT_WM_NCCreate(HWND hwnd, DWORD style, HWND hwndParent, BOOL unicode);
     274static void EDIT_WM_Paint(HWND hwnd, EDITSTATE *es, WPARAM wParam);
     275static void EDIT_WM_Paste(HWND hwnd, EDITSTATE *es);
     276static void EDIT_WM_SetFocus(HWND hwnd, EDITSTATE *es);
     277static void EDIT_WM_SetFont(HWND hwnd, EDITSTATE *es, HFONT font, BOOL redraw);
     278static void EDIT_WM_SetText(HWND hwnd, EDITSTATE *es, LPARAM lParam, BOOL unicode);
     279static void EDIT_WM_Size(HWND hwnd, EDITSTATE *es, UINT action, INT width, INT height);
    279280static LRESULT  EDIT_WM_StyleChanged (HWND hwnd, EDITSTATE *es, WPARAM which, const STYLESTRUCT *style);
    280 static LRESULT  EDIT_WM_SysKeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data);
    281 static void     EDIT_WM_Timer(HWND hwnd, EDITSTATE *es);
    282 static LRESULT  EDIT_WM_VScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos);
     281static LRESULT  EDIT_WM_SysKeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data);
     282static void EDIT_WM_Timer(HWND hwnd, EDITSTATE *es);
     283static LRESULT  EDIT_WM_VScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos);
    283284static void EDIT_UpdateText(HWND hwnd, EDITSTATE *es, LPRECT rc, BOOL bErase);
    284285static void EDIT_UpdateTextRegion(HWND hwnd, EDITSTATE *es, HRGN hrgn, BOOL bErase);
     
    304305/*********************************************************************
    305306 *
    306  *      EM_CANUNDO
     307 *  EM_CANUNDO
    307308 *
    308309 */
    309310static inline BOOL EDIT_EM_CanUndo(EDITSTATE *es)
    310311{
    311         return (es->undo_insert_count || strlenW(es->undo_text));
    312 }
    313 
    314 
    315 /*********************************************************************
    316  *
    317  *      EM_EMPTYUNDOBUFFER
     312    return (es->undo_insert_count || strlenW(es->undo_text));
     313}
     314
     315
     316/*********************************************************************
     317 *
     318 *  EM_EMPTYUNDOBUFFER
    318319 *
    319320 */
    320321static inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es)
    321322{
    322         es->undo_insert_count = 0;
    323         *es->undo_text = '\0';
    324 }
    325 
    326 
    327 /*********************************************************************
    328  *
    329  *      WM_CLEAR
     323    es->undo_insert_count = 0;
     324    *es->undo_text = '\0';
     325}
     326
     327
     328/*********************************************************************
     329 *
     330 *  WM_CLEAR
    330331 *
    331332 */
    332333static inline void EDIT_WM_Clear(HWND hwnd, EDITSTATE *es)
    333334{
    334         static const WCHAR empty_stringW[] = {0};
    335 
    336         /* Protect read-only edit control from modification */
    337         if(es->style & ES_READONLY)
    338             return;
    339 
    340         EDIT_EM_ReplaceSel(hwnd, es, TRUE, empty_stringW, TRUE);
    341 }
    342 
    343 
    344 /*********************************************************************
    345  *
    346  *      WM_CUT
     335    static const WCHAR empty_stringW[] = {0};
     336
     337    /* Protect read-only edit control from modification */
     338    if(es->style & ES_READONLY)
     339        return;
     340
     341    EDIT_EM_ReplaceSel(hwnd, es, TRUE, empty_stringW, TRUE);
     342}
     343
     344
     345/*********************************************************************
     346 *
     347 *  WM_CUT
    347348 *
    348349 */
    349350static inline void EDIT_WM_Cut(HWND hwnd, EDITSTATE *es)
    350351{
    351         EDIT_WM_Copy(hwnd, es);
    352         EDIT_WM_Clear(hwnd, es);
     352    EDIT_WM_Copy(hwnd, es);
     353    EDIT_WM_Clear(hwnd, es);
    353354}
    354355
     
    379380        DWORD dwProcVersion = GetProcessVersion(0);
    380381
    381         info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
     382    info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
    382383        GetVersionExW( &info );
    383384        dwEmulatedVersion = MAKELONG( info.dwMinorVersion, info.dwMajorVersion );
     
    392393/*********************************************************************
    393394 *
    394  *      EditWndProc_common
    395  *
    396  *      The messages are in the order of the actual integer values
    397  *      (which can be found in include/windows.h)
    398  *      Wherever possible the 16 bit versions are converted to
    399  *      the 32 bit ones, so that we can 'fall through' to the
    400  *      helper functions.  These are mostly 32 bit (with a few
    401  *      exceptions, clearly indicated by a '16' extension to their
    402  *      names).
     395 *  EditWndProc_common
     396 *
     397 *  The messages are in the order of the actual integer values
     398 *  (which can be found in include/windows.h)
     399 *  Wherever possible the 16 bit versions are converted to
     400 *  the 32 bit ones, so that we can 'fall through' to the
     401 *  helper functions.  These are mostly 32 bit (with a few
     402 *  exceptions, clearly indicated by a '16' extension to their
     403 *  names).
    403404 *
    404405 */
     
    406407                                          WPARAM wParam, LPARAM lParam, BOOL unicode )
    407408{
    408         EDITSTATE *es = (EDITSTATE *)GetWindowLongA( hwnd, 0 );
    409         LRESULT result = 0;
    410 
    411         switch (msg) {
    412         case WM_DESTROY:
    413                 DPRINTF_EDIT_MSG32("WM_DESTROY");
    414                 if (es) EDIT_WM_Destroy(hwnd, es);
     409    EDITSTATE *es = (EDITSTATE *)GetWindowLongA( hwnd, 0 );
     410    LRESULT result = 0;
     411
     412    switch (msg) {
     413    case WM_DESTROY:
     414        DPRINTF_EDIT_MSG32("WM_DESTROY");
     415        if (es) EDIT_WM_Destroy(hwnd, es);
    415416                result = 0;
    416417                goto END;
    417418
    418         case WM_NCCREATE:
    419                 DPRINTF_EDIT_MSG32("WM_NCCREATE");
    420                 if(unicode)
    421                 {
    422                     LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
    423                     result = EDIT_WM_NCCreate(hwnd, cs->style, cs->hwndParent, TRUE);
    424                 }
    425                 else
    426                 {
    427                     LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
    428                     result = EDIT_WM_NCCreate(hwnd, cs->style, cs->hwndParent, FALSE);
    429                 }
     419    case WM_NCCREATE:
     420        DPRINTF_EDIT_MSG32("WM_NCCREATE");
     421        if(unicode)
     422        {
     423            LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
     424            result = EDIT_WM_NCCreate(hwnd, cs->style, cs->hwndParent, TRUE);
     425        }
     426        else
     427        {
     428            LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
     429            result = EDIT_WM_NCCreate(hwnd, cs->style, cs->hwndParent, FALSE);
     430        }
    430431                goto END;
    431         }
    432 
    433         if (!es)
     432    }
     433
     434    if (!es)
    434435        {
    435             if(unicode)
    436                 result = DefWindowProcW(hwnd, msg, wParam, lParam);
    437             else
    438                 result = DefWindowProcA(hwnd, msg, wParam, lParam);
     436        if(unicode)
     437        result = DefWindowProcW(hwnd, msg, wParam, lParam);
     438        else
     439        result = DefWindowProcA(hwnd, msg, wParam, lParam);
    439440            goto END;
    440441        }
    441442
    442443
    443         EDIT_LockBuffer(hwnd, es);
    444         switch (msg) {
    445         case EM_GETSEL16:
    446                 DPRINTF_EDIT_MSG16("EM_GETSEL");
    447                 wParam = 0;
    448                 lParam = 0;
    449                 /* fall through */
    450         case EM_GETSEL:
    451                 DPRINTF_EDIT_MSG32("EM_GETSEL");
    452                 result = EDIT_EM_GetSel(es, (LPUINT)wParam, (LPUINT)lParam);
    453                 break;
    454 
    455         case EM_SETSEL16:
    456                 DPRINTF_EDIT_MSG16("EM_SETSEL");
    457                 if (SLOWORD(lParam) == -1)
    458                         EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
    459                 else
    460                         EDIT_EM_SetSel(hwnd, es, LOWORD(lParam), HIWORD(lParam), FALSE);
    461                 if (!wParam)
    462                         EDIT_EM_ScrollCaret(hwnd, es);
    463                 result = 1;
    464                 break;
    465         case EM_SETSEL:
    466                 DPRINTF_EDIT_MSG32("EM_SETSEL");
    467                 EDIT_EM_SetSel(hwnd, es, wParam, lParam, FALSE);
    468                 EDIT_EM_ScrollCaret(hwnd, es);
    469                 result = 1;
    470                 break;
    471 
    472         case EM_GETRECT16:
    473                 DPRINTF_EDIT_MSG16("EM_GETRECT");
    474                 if (lParam)
    475                         CONV_RECT32TO16(&es->format_rect, MapSL(lParam));
    476                 break;
    477         case EM_GETRECT:
    478                 DPRINTF_EDIT_MSG32("EM_GETRECT");
    479                 if (lParam)
    480                         CopyRect((LPRECT)lParam, &es->format_rect);
    481                 break;
    482 
    483         case EM_SETRECT16:
    484                 DPRINTF_EDIT_MSG16("EM_SETRECT");
    485                 if ((es->style & ES_MULTILINE) && lParam) {
    486                         RECT rc;
    487                         CONV_RECT16TO32(MapSL(lParam), &rc);
    488                         EDIT_SetRectNP(hwnd, es, &rc);
    489                         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    490                 }
    491                 break;
    492         case EM_SETRECT:
    493                 DPRINTF_EDIT_MSG32("EM_SETRECT");
    494                 if ((es->style & ES_MULTILINE) && lParam) {
    495                         EDIT_SetRectNP(hwnd, es, (LPRECT)lParam);
    496                         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    497                 }
    498                 break;
    499 
    500         case EM_SETRECTNP16:
    501                 DPRINTF_EDIT_MSG16("EM_SETRECTNP");
    502                 if ((es->style & ES_MULTILINE) && lParam) {
    503                         RECT rc;
    504                         CONV_RECT16TO32(MapSL(lParam), &rc);
    505                         EDIT_SetRectNP(hwnd, es, &rc);
    506                 }
    507                 break;
    508         case EM_SETRECTNP:
    509                 DPRINTF_EDIT_MSG32("EM_SETRECTNP");
    510                 if ((es->style & ES_MULTILINE) && lParam)
    511                         EDIT_SetRectNP(hwnd, es, (LPRECT)lParam);
    512                 break;
    513 
    514         case EM_SCROLL16:
    515                 DPRINTF_EDIT_MSG16("EM_SCROLL");
    516                 /* fall through */
    517         case EM_SCROLL:
    518                 DPRINTF_EDIT_MSG32("EM_SCROLL");
    519                 result = EDIT_EM_Scroll(hwnd, es, (INT)wParam);
    520                 break;
    521 
    522         case EM_LINESCROLL16:
    523                 DPRINTF_EDIT_MSG16("EM_LINESCROLL");
    524                 wParam = (WPARAM)(INT)SHIWORD(lParam);
    525                 lParam = (LPARAM)(INT)SLOWORD(lParam);
    526                 /* fall through */
    527         case EM_LINESCROLL:
    528                 DPRINTF_EDIT_MSG32("EM_LINESCROLL");
    529                 result = (LRESULT)EDIT_EM_LineScroll(hwnd, es, (INT)wParam, (INT)lParam);
    530                 break;
    531 
    532         case EM_SCROLLCARET16:
    533                 DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
    534                 /* fall through */
    535         case EM_SCROLLCARET:
    536                 DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
    537                 EDIT_EM_ScrollCaret(hwnd, es);
    538                 result = 1;
    539                 break;
    540 
    541         case EM_GETMODIFY16:
    542                 DPRINTF_EDIT_MSG16("EM_GETMODIFY");
    543                 /* fall through */
    544         case EM_GETMODIFY:
    545                 DPRINTF_EDIT_MSG32("EM_GETMODIFY");
    546                 result = ((es->flags & EF_MODIFIED) != 0);
    547                 break;
    548 
    549         case EM_SETMODIFY16:
    550                 DPRINTF_EDIT_MSG16("EM_SETMODIFY");
    551                 /* fall through */
    552         case EM_SETMODIFY:
    553                 DPRINTF_EDIT_MSG32("EM_SETMODIFY");
    554                 if (wParam)
    555                         es->flags |= EF_MODIFIED;
    556                 else
     444    EDIT_LockBuffer(hwnd, es);
     445    switch (msg) {
     446    case EM_GETSEL16:
     447        DPRINTF_EDIT_MSG16("EM_GETSEL");
     448        wParam = 0;
     449        lParam = 0;
     450        /* fall through */
     451    case EM_GETSEL:
     452        DPRINTF_EDIT_MSG32("EM_GETSEL");
     453        result = EDIT_EM_GetSel(es, (LPUINT)wParam, (LPUINT)lParam);
     454        break;
     455
     456    case EM_SETSEL16:
     457        DPRINTF_EDIT_MSG16("EM_SETSEL");
     458        if (SLOWORD(lParam) == -1)
     459            EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     460        else
     461            EDIT_EM_SetSel(hwnd, es, LOWORD(lParam), HIWORD(lParam), FALSE);
     462        if (!wParam)
     463            EDIT_EM_ScrollCaret(hwnd, es);
     464        result = 1;
     465        break;
     466    case EM_SETSEL:
     467        DPRINTF_EDIT_MSG32("EM_SETSEL");
     468        EDIT_EM_SetSel(hwnd, es, wParam, lParam, FALSE);
     469        EDIT_EM_ScrollCaret(hwnd, es);
     470        result = 1;
     471        break;
     472
     473    case EM_GETRECT16:
     474        DPRINTF_EDIT_MSG16("EM_GETRECT");
     475        if (lParam)
     476            CONV_RECT32TO16(&es->format_rect, MapSL(lParam));
     477        break;
     478    case EM_GETRECT:
     479        DPRINTF_EDIT_MSG32("EM_GETRECT");
     480        if (lParam)
     481            CopyRect((LPRECT)lParam, &es->format_rect);
     482        break;
     483
     484    case EM_SETRECT16:
     485        DPRINTF_EDIT_MSG16("EM_SETRECT");
     486        if ((es->style & ES_MULTILINE) && lParam) {
     487            RECT rc;
     488            CONV_RECT16TO32(MapSL(lParam), &rc);
     489            EDIT_SetRectNP(hwnd, es, &rc);
     490            EDIT_UpdateText(hwnd, es, NULL, TRUE);
     491        }
     492        break;
     493    case EM_SETRECT:
     494        DPRINTF_EDIT_MSG32("EM_SETRECT");
     495        if ((es->style & ES_MULTILINE) && lParam) {
     496            EDIT_SetRectNP(hwnd, es, (LPRECT)lParam);
     497            EDIT_UpdateText(hwnd, es, NULL, TRUE);
     498        }
     499        break;
     500
     501    case EM_SETRECTNP16:
     502        DPRINTF_EDIT_MSG16("EM_SETRECTNP");
     503        if ((es->style & ES_MULTILINE) && lParam) {
     504            RECT rc;
     505            CONV_RECT16TO32(MapSL(lParam), &rc);
     506            EDIT_SetRectNP(hwnd, es, &rc);
     507        }
     508        break;
     509    case EM_SETRECTNP:
     510        DPRINTF_EDIT_MSG32("EM_SETRECTNP");
     511        if ((es->style & ES_MULTILINE) && lParam)
     512            EDIT_SetRectNP(hwnd, es, (LPRECT)lParam);
     513        break;
     514
     515    case EM_SCROLL16:
     516        DPRINTF_EDIT_MSG16("EM_SCROLL");
     517        /* fall through */
     518    case EM_SCROLL:
     519        DPRINTF_EDIT_MSG32("EM_SCROLL");
     520        result = EDIT_EM_Scroll(hwnd, es, (INT)wParam);
     521        break;
     522
     523    case EM_LINESCROLL16:
     524        DPRINTF_EDIT_MSG16("EM_LINESCROLL");
     525        wParam = (WPARAM)(INT)SHIWORD(lParam);
     526        lParam = (LPARAM)(INT)SLOWORD(lParam);
     527        /* fall through */
     528    case EM_LINESCROLL:
     529        DPRINTF_EDIT_MSG32("EM_LINESCROLL");
     530        result = (LRESULT)EDIT_EM_LineScroll(hwnd, es, (INT)wParam, (INT)lParam);
     531        break;
     532
     533    case EM_SCROLLCARET16:
     534        DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
     535        /* fall through */
     536    case EM_SCROLLCARET:
     537        DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
     538        EDIT_EM_ScrollCaret(hwnd, es);
     539        result = 1;
     540        break;
     541
     542    case EM_GETMODIFY16:
     543        DPRINTF_EDIT_MSG16("EM_GETMODIFY");
     544        /* fall through */
     545    case EM_GETMODIFY:
     546        DPRINTF_EDIT_MSG32("EM_GETMODIFY");
     547        result = ((es->flags & EF_MODIFIED) != 0);
     548        break;
     549
     550    case EM_SETMODIFY16:
     551        DPRINTF_EDIT_MSG16("EM_SETMODIFY");
     552        /* fall through */
     553    case EM_SETMODIFY:
     554        DPRINTF_EDIT_MSG32("EM_SETMODIFY");
     555        if (wParam)
     556            es->flags |= EF_MODIFIED;
     557        else
    557558                        es->flags &= ~(EF_MODIFIED | EF_UPDATE);  /* reset pending updates */
    558                 break;
    559 
    560         case EM_GETLINECOUNT16:
    561                 DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
    562                 /* fall through */
    563         case EM_GETLINECOUNT:
    564                 DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
    565                 result = (es->style & ES_MULTILINE) ? es->line_count : 1;
    566                 break;
    567 
    568         case EM_LINEINDEX16:
    569                 DPRINTF_EDIT_MSG16("EM_LINEINDEX");
    570                 if ((INT16)wParam == -1)
    571                         wParam = (WPARAM)-1;
    572                 /* fall through */
    573         case EM_LINEINDEX:
    574                 DPRINTF_EDIT_MSG32("EM_LINEINDEX");
    575                 result = (LRESULT)EDIT_EM_LineIndex(es, (INT)wParam);
    576                 break;
     559        break;
     560
     561    case EM_GETLINECOUNT16:
     562        DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
     563        /* fall through */
     564    case EM_GETLINECOUNT:
     565        DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
     566        result = (es->style & ES_MULTILINE) ? es->line_count : 1;
     567        break;
     568
     569    case EM_LINEINDEX16:
     570        DPRINTF_EDIT_MSG16("EM_LINEINDEX");
     571        if ((INT16)wParam == -1)
     572            wParam = (WPARAM)-1;
     573        /* fall through */
     574    case EM_LINEINDEX:
     575        DPRINTF_EDIT_MSG32("EM_LINEINDEX");
     576        result = (LRESULT)EDIT_EM_LineIndex(es, (INT)wParam);
     577        break;
    577578
    578579#ifndef __WIN32OS2__
    579         case EM_SETHANDLE16:
    580                 DPRINTF_EDIT_MSG16("EM_SETHANDLE");
    581                 EDIT_EM_SetHandle16(hwnd, es, (HLOCAL16)wParam);
    582                 break;
     580    case EM_SETHANDLE16:
     581        DPRINTF_EDIT_MSG16("EM_SETHANDLE");
     582        EDIT_EM_SetHandle16(hwnd, es, (HLOCAL16)wParam);
     583        break;
    583584#endif
    584         case EM_SETHANDLE:
    585                 DPRINTF_EDIT_MSG32("EM_SETHANDLE");
    586                 EDIT_EM_SetHandle(hwnd, es, (HLOCAL)wParam);
    587                 break;
     585    case EM_SETHANDLE:
     586        DPRINTF_EDIT_MSG32("EM_SETHANDLE");
     587        EDIT_EM_SetHandle(hwnd, es, (HLOCAL)wParam);
     588        break;
    588589
    589590#ifndef __WIN32OS2__
    590         case EM_GETHANDLE16:
    591                 DPRINTF_EDIT_MSG16("EM_GETHANDLE");
    592                 result = (LRESULT)EDIT_EM_GetHandle16(hwnd, es);
    593                 break;
     591    case EM_GETHANDLE16:
     592        DPRINTF_EDIT_MSG16("EM_GETHANDLE");
     593        result = (LRESULT)EDIT_EM_GetHandle16(hwnd, es);
     594        break;
    594595#endif
    595         case EM_GETHANDLE:
    596                 DPRINTF_EDIT_MSG32("EM_GETHANDLE");
    597                 result = (LRESULT)EDIT_EM_GetHandle(es);
    598                 break;
    599 
    600         case EM_GETTHUMB16:
    601                 DPRINTF_EDIT_MSG16("EM_GETTHUMB");
    602                 /* fall through */
    603         case EM_GETTHUMB:
    604                 DPRINTF_EDIT_MSG32("EM_GETTHUMB");
    605                 result = EDIT_EM_GetThumb(hwnd, es);
    606                 break;
    607 
    608         /* messages 0x00bf and 0x00c0 missing from specs */
    609 
    610         case WM_USER+15:
    611                 DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
    612                 /* fall through */
    613         case 0x00bf:
    614                 DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
    615                 result = DefWindowProcW(hwnd, msg, wParam, lParam);
    616                 break;
    617 
    618         case WM_USER+16:
    619                 DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
    620                 /* fall through */
    621         case 0x00c0:
    622                 DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
    623                 result = DefWindowProcW(hwnd, msg, wParam, lParam);
    624                 break;
    625 
    626         case EM_LINELENGTH16:
    627                 DPRINTF_EDIT_MSG16("EM_LINELENGTH");
    628                 /* fall through */
    629         case EM_LINELENGTH:
    630                 DPRINTF_EDIT_MSG32("EM_LINELENGTH");
    631                 result = (LRESULT)EDIT_EM_LineLength(es, (INT)wParam);
    632                 break;
    633 
    634         case EM_REPLACESEL16:
    635                 DPRINTF_EDIT_MSG16("EM_REPLACESEL");
    636                 lParam = (LPARAM)MapSL(lParam);
    637                 unicode = FALSE;  /* 16-bit message is always ascii */
    638                 /* fall through */
    639         case EM_REPLACESEL:
    640         {
    641                 LPWSTR textW;
    642                 DPRINTF_EDIT_MSG32("EM_REPLACESEL");
    643 
    644                 if(unicode)
    645                     textW = (LPWSTR)lParam;
    646                 else
    647                 {
    648                     LPSTR textA = (LPSTR)lParam;
    649                     INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
    650                     if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
    651                         MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
    652                 }
    653 
    654                 EDIT_EM_ReplaceSel(hwnd, es, (BOOL)wParam, textW, TRUE);
    655                 result = 1;
    656 
    657                 if(!unicode)
    658                     HeapFree(GetProcessHeap(), 0, textW);
    659                 break;
    660         }
    661         /* message 0x00c3 missing from specs */
    662 
    663         case WM_USER+19:
    664                 DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
    665                 /* fall through */
    666         case 0x00c3:
    667                 DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
    668                 result = DefWindowProcW(hwnd, msg, wParam, lParam);
    669                 break;
    670 
    671         case EM_GETLINE16:
    672                 DPRINTF_EDIT_MSG16("EM_GETLINE");
    673                 lParam = (LPARAM)MapSL(lParam);
    674                 unicode = FALSE;  /* 16-bit message is always ascii */
    675                 /* fall through */
    676         case EM_GETLINE:
    677                 DPRINTF_EDIT_MSG32("EM_GETLINE");
    678                 result = (LRESULT)EDIT_EM_GetLine(es, (INT)wParam, lParam, unicode);
    679                 break;
    680 
    681         case EM_LIMITTEXT16:
    682                 DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
    683                 /* fall through */
    684         case EM_SETLIMITTEXT:
    685                 DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
    686                 EDIT_EM_SetLimitText(es, (INT)wParam);
    687                 break;
    688 
    689         case EM_CANUNDO16:
    690                 DPRINTF_EDIT_MSG16("EM_CANUNDO");
    691                 /* fall through */
    692         case EM_CANUNDO:
    693                 DPRINTF_EDIT_MSG32("EM_CANUNDO");
    694                 result = (LRESULT)EDIT_EM_CanUndo(es);
    695                 break;
    696 
    697         case EM_UNDO16:
    698                 DPRINTF_EDIT_MSG16("EM_UNDO");
    699                 /* fall through */
    700         case EM_UNDO:
    701                 /* fall through */
    702         case WM_UNDO:
    703                 DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
    704                 result = (LRESULT)EDIT_EM_Undo(hwnd, es);
    705                 break;
    706 
    707         case EM_FMTLINES16:
    708                 DPRINTF_EDIT_MSG16("EM_FMTLINES");
    709                 /* fall through */
    710         case EM_FMTLINES:
    711                 DPRINTF_EDIT_MSG32("EM_FMTLINES");
    712                 result = (LRESULT)EDIT_EM_FmtLines(es, (BOOL)wParam);
    713                 break;
    714 
    715         case EM_LINEFROMCHAR16:
    716                 DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
    717                 /* fall through */
    718         case EM_LINEFROMCHAR:
    719                 DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
    720                 result = (LRESULT)EDIT_EM_LineFromChar(es, (INT)wParam);
    721                 break;
    722 
    723         /* message 0x00ca missing from specs */
    724 
    725         case WM_USER+26:
    726                 DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
    727                 /* fall through */
    728         case 0x00ca:
    729                 DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
    730                 result = DefWindowProcW(hwnd, msg, wParam, lParam);
    731                 break;
    732 
    733         case EM_SETTABSTOPS16:
    734                 DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
    735                 result = (LRESULT)EDIT_EM_SetTabStops16(es, (INT)wParam, MapSL(lParam));
    736                 break;
    737         case EM_SETTABSTOPS:
    738                 DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
    739                 result = (LRESULT)EDIT_EM_SetTabStops(es, (INT)wParam, (LPINT)lParam);
    740                 break;
    741 
    742         case EM_SETPASSWORDCHAR16:
    743                 DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
    744                 unicode = FALSE;  /* 16-bit message is always ascii */
    745                 /* fall through */
    746         case EM_SETPASSWORDCHAR:
    747         {
    748                 WCHAR charW = 0;
    749                 DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
    750 
    751                 if(unicode)
    752                     charW = (WCHAR)wParam;
    753                 else
    754                 {
    755                     CHAR charA = wParam;
    756                     MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
    757                 }
    758 
    759                 EDIT_EM_SetPasswordChar(hwnd, es, charW);
    760                 break;
    761         }
    762 
    763         case EM_EMPTYUNDOBUFFER16:
    764                 DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
    765                 /* fall through */
    766         case EM_EMPTYUNDOBUFFER:
    767                 DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
    768                 EDIT_EM_EmptyUndoBuffer(es);
    769                 break;
    770 
    771         case EM_GETFIRSTVISIBLELINE16:
    772                 DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
    773                 result = es->y_offset;
    774                 break;
    775         case EM_GETFIRSTVISIBLELINE:
    776                 DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
    777                 result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
    778                 break;
    779 
    780         case EM_SETREADONLY16:
    781                 DPRINTF_EDIT_MSG16("EM_SETREADONLY");
    782                 /* fall through */
    783         case EM_SETREADONLY:
    784                 DPRINTF_EDIT_MSG32("EM_SETREADONLY");
    785                 if (wParam) {
     596    case EM_GETHANDLE:
     597        DPRINTF_EDIT_MSG32("EM_GETHANDLE");
     598        result = (LRESULT)EDIT_EM_GetHandle(es);
     599        break;
     600
     601    case EM_GETTHUMB16:
     602        DPRINTF_EDIT_MSG16("EM_GETTHUMB");
     603        /* fall through */
     604    case EM_GETTHUMB:
     605        DPRINTF_EDIT_MSG32("EM_GETTHUMB");
     606        result = EDIT_EM_GetThumb(hwnd, es);
     607        break;
     608
     609    /* messages 0x00bf and 0x00c0 missing from specs */
     610
     611    case WM_USER+15:
     612        DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
     613        /* fall through */
     614    case 0x00bf:
     615        DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
     616        result = DefWindowProcW(hwnd, msg, wParam, lParam);
     617        break;
     618
     619    case WM_USER+16:
     620        DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
     621        /* fall through */
     622    case 0x00c0:
     623        DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
     624        result = DefWindowProcW(hwnd, msg, wParam, lParam);
     625        break;
     626
     627    case EM_LINELENGTH16:
     628        DPRINTF_EDIT_MSG16("EM_LINELENGTH");
     629        /* fall through */
     630    case EM_LINELENGTH:
     631        DPRINTF_EDIT_MSG32("EM_LINELENGTH");
     632        result = (LRESULT)EDIT_EM_LineLength(es, (INT)wParam);
     633        break;
     634
     635    case EM_REPLACESEL16:
     636        DPRINTF_EDIT_MSG16("EM_REPLACESEL");
     637        lParam = (LPARAM)MapSL(lParam);
     638        unicode = FALSE;  /* 16-bit message is always ascii */
     639        /* fall through */
     640    case EM_REPLACESEL:
     641    {
     642        LPWSTR textW;
     643        DPRINTF_EDIT_MSG32("EM_REPLACESEL");
     644
     645        if(unicode)
     646            textW = (LPWSTR)lParam;
     647        else
     648        {
     649            LPSTR textA = (LPSTR)lParam;
     650            INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
     651            if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
     652            MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
     653        }
     654
     655        EDIT_EM_ReplaceSel(hwnd, es, (BOOL)wParam, textW, TRUE);
     656        result = 1;
     657
     658        if(!unicode)
     659            HeapFree(GetProcessHeap(), 0, textW);
     660        break;
     661    }
     662    /* message 0x00c3 missing from specs */
     663
     664    case WM_USER+19:
     665        DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
     666        /* fall through */
     667    case 0x00c3:
     668        DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
     669        result = DefWindowProcW(hwnd, msg, wParam, lParam);
     670        break;
     671
     672    case EM_GETLINE16:
     673        DPRINTF_EDIT_MSG16("EM_GETLINE");
     674        lParam = (LPARAM)MapSL(lParam);
     675        unicode = FALSE;  /* 16-bit message is always ascii */
     676        /* fall through */
     677    case EM_GETLINE:
     678        DPRINTF_EDIT_MSG32("EM_GETLINE");
     679        result = (LRESULT)EDIT_EM_GetLine(es, (INT)wParam, lParam, unicode);
     680        break;
     681
     682    case EM_LIMITTEXT16:
     683        DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
     684        /* fall through */
     685    case EM_SETLIMITTEXT:
     686        DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
     687        EDIT_EM_SetLimitText(es, (INT)wParam);
     688        break;
     689
     690    case EM_CANUNDO16:
     691        DPRINTF_EDIT_MSG16("EM_CANUNDO");
     692        /* fall through */
     693    case EM_CANUNDO:
     694        DPRINTF_EDIT_MSG32("EM_CANUNDO");
     695        result = (LRESULT)EDIT_EM_CanUndo(es);
     696        break;
     697
     698    case EM_UNDO16:
     699        DPRINTF_EDIT_MSG16("EM_UNDO");
     700        /* fall through */
     701    case EM_UNDO:
     702        /* fall through */
     703    case WM_UNDO:
     704        DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
     705        result = (LRESULT)EDIT_EM_Undo(hwnd, es);
     706        break;
     707
     708    case EM_FMTLINES16:
     709        DPRINTF_EDIT_MSG16("EM_FMTLINES");
     710        /* fall through */
     711    case EM_FMTLINES:
     712        DPRINTF_EDIT_MSG32("EM_FMTLINES");
     713        result = (LRESULT)EDIT_EM_FmtLines(es, (BOOL)wParam);
     714        break;
     715
     716    case EM_LINEFROMCHAR16:
     717        DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
     718        /* fall through */
     719    case EM_LINEFROMCHAR:
     720        DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
     721        result = (LRESULT)EDIT_EM_LineFromChar(es, (INT)wParam);
     722        break;
     723
     724    /* message 0x00ca missing from specs */
     725
     726    case WM_USER+26:
     727        DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
     728        /* fall through */
     729    case 0x00ca:
     730        DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
     731        result = DefWindowProcW(hwnd, msg, wParam, lParam);
     732        break;
     733
     734    case EM_SETTABSTOPS16:
     735        DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
     736        result = (LRESULT)EDIT_EM_SetTabStops16(es, (INT)wParam, MapSL(lParam));
     737        break;
     738    case EM_SETTABSTOPS:
     739        DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
     740        result = (LRESULT)EDIT_EM_SetTabStops(es, (INT)wParam, (LPINT)lParam);
     741        break;
     742
     743    case EM_SETPASSWORDCHAR16:
     744        DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
     745        unicode = FALSE;  /* 16-bit message is always ascii */
     746        /* fall through */
     747    case EM_SETPASSWORDCHAR:
     748    {
     749        WCHAR charW = 0;
     750        DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
     751
     752        if(unicode)
     753            charW = (WCHAR)wParam;
     754        else
     755        {
     756            CHAR charA = wParam;
     757            MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
     758        }
     759
     760        EDIT_EM_SetPasswordChar(hwnd, es, charW);
     761        break;
     762    }
     763
     764    case EM_EMPTYUNDOBUFFER16:
     765        DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
     766        /* fall through */
     767    case EM_EMPTYUNDOBUFFER:
     768        DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
     769        EDIT_EM_EmptyUndoBuffer(es);
     770        break;
     771
     772    case EM_GETFIRSTVISIBLELINE16:
     773        DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
     774        result = es->y_offset;
     775        break;
     776    case EM_GETFIRSTVISIBLELINE:
     777        DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
     778        result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
     779        break;
     780
     781    case EM_SETREADONLY16:
     782        DPRINTF_EDIT_MSG16("EM_SETREADONLY");
     783        /* fall through */
     784    case EM_SETREADONLY:
     785        DPRINTF_EDIT_MSG32("EM_SETREADONLY");
     786        if (wParam) {
    786787                    SetWindowLongA( hwnd, GWL_STYLE,
    787788                                    GetWindowLongA( hwnd, GWL_STYLE ) | ES_READONLY );
    788789                    es->style |= ES_READONLY;
    789                 } else {
     790        } else {
    790791                    SetWindowLongA( hwnd, GWL_STYLE,
    791792                                    GetWindowLongA( hwnd, GWL_STYLE ) & ~ES_READONLY );
    792793                    es->style &= ~ES_READONLY;
    793                 }
     794        }
    794795                result = 1;
    795                 break;
     796        break;
    796797#ifndef __WIN32OS2__
    797         case EM_SETWORDBREAKPROC16:
    798                 DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
    799                 EDIT_EM_SetWordBreakProc16(hwnd, es, (EDITWORDBREAKPROC16)lParam);
    800                 break;
     798    case EM_SETWORDBREAKPROC16:
     799        DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
     800        EDIT_EM_SetWordBreakProc16(hwnd, es, (EDITWORDBREAKPROC16)lParam);
     801        break;
    801802#endif
    802         case EM_SETWORDBREAKPROC:
    803                 DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
    804                 EDIT_EM_SetWordBreakProc(hwnd, es, lParam);
    805                 break;
    806 
    807         case EM_GETWORDBREAKPROC16:
    808                 DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
    809                 result = (LRESULT)es->word_break_proc16;
    810                 break;
    811         case EM_GETWORDBREAKPROC:
    812                 DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
    813                 result = (LRESULT)es->word_break_proc;
    814                 break;
    815 
    816         case EM_GETPASSWORDCHAR16:
    817                 DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
    818                 unicode = FALSE;  /* 16-bit message is always ascii */
    819                 /* fall through */
    820         case EM_GETPASSWORDCHAR:
    821         {
    822                 DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
    823 
    824                 if(unicode)
    825                     result = es->password_char;
    826                 else
    827                 {
    828                     WCHAR charW = es->password_char;
    829                     CHAR charA = 0;
    830                     WideCharToMultiByte(CP_ACP, 0, &charW, 1, &charA, 1, NULL, NULL);
    831                     result = charA;
    832                 }
    833                 break;
    834         }
    835 
    836         /* The following EM_xxx are new to win95 and don't exist for 16 bit */
    837 
    838         case EM_SETMARGINS:
    839                 DPRINTF_EDIT_MSG32("EM_SETMARGINS");
    840                 EDIT_EM_SetMargins(es, (INT)wParam, SLOWORD(lParam), SHIWORD(lParam));
    841                 break;
    842 
    843         case EM_GETMARGINS:
    844                 DPRINTF_EDIT_MSG32("EM_GETMARGINS");
    845                 result = MAKELONG(es->left_margin, es->right_margin);
    846                 break;
    847 
    848         case EM_GETLIMITTEXT:
    849                 DPRINTF_EDIT_MSG32("EM_GETLIMITTEXT");
    850                 result = es->buffer_limit;
    851                 break;
    852 
    853         case EM_POSFROMCHAR:
    854                 DPRINTF_EDIT_MSG32("EM_POSFROMCHAR");
    855                 result = EDIT_EM_PosFromChar(hwnd, es, (INT)wParam, FALSE);
    856                 break;
    857 
    858         case EM_CHARFROMPOS:
    859                 DPRINTF_EDIT_MSG32("EM_CHARFROMPOS");
    860                 result = EDIT_EM_CharFromPos(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
    861                 break;
     803    case EM_SETWORDBREAKPROC:
     804        DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
     805        EDIT_EM_SetWordBreakProc(hwnd, es, lParam);
     806        break;
     807
     808    case EM_GETWORDBREAKPROC16:
     809        DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
     810        result = (LRESULT)es->word_break_proc16;
     811        break;
     812    case EM_GETWORDBREAKPROC:
     813        DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
     814        result = (LRESULT)es->word_break_proc;
     815        break;
     816
     817    case EM_GETPASSWORDCHAR16:
     818        DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
     819        unicode = FALSE;  /* 16-bit message is always ascii */
     820        /* fall through */
     821    case EM_GETPASSWORDCHAR:
     822    {
     823        DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
     824
     825        if(unicode)
     826            result = es->password_char;
     827        else
     828        {
     829            WCHAR charW = es->password_char;
     830            CHAR charA = 0;
     831            WideCharToMultiByte(CP_ACP, 0, &charW, 1, &charA, 1, NULL, NULL);
     832            result = charA;
     833        }
     834        break;
     835    }
     836
     837    /* The following EM_xxx are new to win95 and don't exist for 16 bit */
     838
     839    case EM_SETMARGINS:
     840        DPRINTF_EDIT_MSG32("EM_SETMARGINS");
     841        EDIT_EM_SetMargins(es, (INT)wParam, SLOWORD(lParam), SHIWORD(lParam));
     842        break;
     843
     844    case EM_GETMARGINS:
     845        DPRINTF_EDIT_MSG32("EM_GETMARGINS");
     846        result = MAKELONG(es->left_margin, es->right_margin);
     847        break;
     848
     849    case EM_GETLIMITTEXT:
     850        DPRINTF_EDIT_MSG32("EM_GETLIMITTEXT");
     851        result = es->buffer_limit;
     852        break;
     853
     854    case EM_POSFROMCHAR:
     855        DPRINTF_EDIT_MSG32("EM_POSFROMCHAR");
     856        result = EDIT_EM_PosFromChar(hwnd, es, (INT)wParam, FALSE);
     857        break;
     858
     859    case EM_CHARFROMPOS:
     860        DPRINTF_EDIT_MSG32("EM_CHARFROMPOS");
     861        result = EDIT_EM_CharFromPos(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
     862        break;
    862863
    863864        /* End of the EM_ messages which were in numerical order; what order
     
    865866         */
    866867
    867         case WM_GETDLGCODE:
    868                 DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
    869                 result = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
    870 
    871                 if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
    872                 {
    873                    int vk = (int)((LPMSG)lParam)->wParam;
    874 
    875                    if (vk == VK_RETURN && (GetWindowLongA( hwnd, GWL_STYLE ) & ES_WANTRETURN))
    876                    {
    877                       result |= DLGC_WANTMESSAGE;
    878                    }
    879                    else if (es->hwndListBox && (vk == VK_RETURN || vk == VK_ESCAPE))
    880                    {
    881                       if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0))
    882                          result |= DLGC_WANTMESSAGE;
    883                    }
    884                 }
    885                 break;
    886 
    887         case WM_CHAR:
    888         {
     868    case WM_GETDLGCODE:
     869        DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
     870        result = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
     871
     872        if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
     873        {
     874           int vk = (int)((LPMSG)lParam)->wParam;
     875
     876           if (vk == VK_RETURN && (GetWindowLongA( hwnd, GWL_STYLE ) & ES_WANTRETURN))
     877           {
     878              result |= DLGC_WANTMESSAGE;
     879           }
     880           else if (es->hwndListBox && (vk == VK_RETURN || vk == VK_ESCAPE))
     881           {
     882              if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0))
     883                 result |= DLGC_WANTMESSAGE;
     884           }
     885        }
     886        break;
     887
     888    case WM_CHAR:
     889    {
     890#ifdef __WIN32OS2__
     891        static BOOL bDbcsLead = FALSE;
     892        static CHAR cDbcsLead = 0;
     893
     894        WCHAR charW;
     895        DPRINTF_EDIT_MSG32("WM_CHAR");
     896
     897        if(unicode)
     898            charW = wParam;
     899        else
     900        {
     901            WCHAR charA = bDbcsLead ? (( wParam << 8 ) | cDbcsLead ) : wParam;
     902            int   size = bDbcsLead ? 2 : 1;
     903
     904            bDbcsLead = !bDbcsLead && IsDBCSLeadByte( wParam );
     905
     906            if( bDbcsLead )
     907                cDbcsLead = wParam;
     908            else
     909                MultiByteToWideChar(CP_ACP, 0, (LPSTR)&charA, size, &charW, 1);
     910        }
     911
     912        if ((charW == VK_RETURN || charW == VK_ESCAPE) && es->hwndListBox)
     913        {
     914           if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0))
     915              SendMessageW(GetParent(hwnd), WM_KEYDOWN, charW, 0);
     916           break;
     917        }
     918        if( !bDbcsLead )
     919            EDIT_WM_Char(hwnd, es, charW);
     920#else
    889921                WCHAR charW;
    890922                DPRINTF_EDIT_MSG32("WM_CHAR");
     
    905937                }
    906938                EDIT_WM_Char(hwnd, es, charW);
    907                 break;
    908         }
    909 
    910         case WM_CLEAR:
    911                 DPRINTF_EDIT_MSG32("WM_CLEAR");
    912                 EDIT_WM_Clear(hwnd, es);
    913                 break;
    914 
    915         case WM_COMMAND:
    916                 DPRINTF_EDIT_MSG32("WM_COMMAND");
    917                 EDIT_WM_Command(hwnd, es, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
    918                 break;
    919 
    920         case WM_CONTEXTMENU:
    921                 DPRINTF_EDIT_MSG32("WM_CONTEXTMENU");
    922                 EDIT_WM_ContextMenu(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
    923                 break;
    924 
    925         case WM_COPY:
    926                 DPRINTF_EDIT_MSG32("WM_COPY");
    927                 EDIT_WM_Copy(hwnd, es);
    928                 break;
    929 
    930         case WM_CREATE:
    931                 DPRINTF_EDIT_MSG32("WM_CREATE");
    932                 if(unicode)
    933                     result = EDIT_WM_Create(hwnd, es, ((LPCREATESTRUCTW)lParam)->lpszName);
    934                 else
    935                 {
    936                     LPCSTR nameA = ((LPCREATESTRUCTA)lParam)->lpszName;
    937                     LPWSTR nameW = NULL;
    938                     if(nameA)
    939                     {
    940                         INT countW = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0);
    941                         if((nameW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
    942                             MultiByteToWideChar(CP_ACP, 0, nameA, -1, nameW, countW);
    943                     }
    944                     result = EDIT_WM_Create(hwnd, es, nameW);
    945                     if(nameW)
    946                         HeapFree(GetProcessHeap(), 0, nameW);
    947                 }
    948                 break;
    949 
    950         case WM_CUT:
    951                 DPRINTF_EDIT_MSG32("WM_CUT");
    952                 EDIT_WM_Cut(hwnd, es);
    953                 break;
    954 
    955         case WM_ENABLE:
    956                 DPRINTF_EDIT_MSG32("WM_ENABLE");
     939#endif
     940        break;
     941    }
     942
     943    case WM_CLEAR:
     944        DPRINTF_EDIT_MSG32("WM_CLEAR");
     945        EDIT_WM_Clear(hwnd, es);
     946        break;
     947
     948    case WM_COMMAND:
     949        DPRINTF_EDIT_MSG32("WM_COMMAND");
     950        EDIT_WM_Command(hwnd, es, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
     951        break;
     952
     953    case WM_CONTEXTMENU:
     954        DPRINTF_EDIT_MSG32("WM_CONTEXTMENU");
     955        EDIT_WM_ContextMenu(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
     956        break;
     957
     958    case WM_COPY:
     959        DPRINTF_EDIT_MSG32("WM_COPY");
     960        EDIT_WM_Copy(hwnd, es);
     961        break;
     962
     963    case WM_CREATE:
     964        DPRINTF_EDIT_MSG32("WM_CREATE");
     965        if(unicode)
     966            result = EDIT_WM_Create(hwnd, es, ((LPCREATESTRUCTW)lParam)->lpszName);
     967        else
     968        {
     969            LPCSTR nameA = ((LPCREATESTRUCTA)lParam)->lpszName;
     970            LPWSTR nameW = NULL;
     971            if(nameA)
     972            {
     973            INT countW = MultiByteToWideChar(CP_ACP, 0, nameA, -1, NULL, 0);
     974            if((nameW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
     975                MultiByteToWideChar(CP_ACP, 0, nameA, -1, nameW, countW);
     976            }
     977            result = EDIT_WM_Create(hwnd, es, nameW);
     978            if(nameW)
     979            HeapFree(GetProcessHeap(), 0, nameW);
     980        }
     981        break;
     982
     983    case WM_CUT:
     984        DPRINTF_EDIT_MSG32("WM_CUT");
     985        EDIT_WM_Cut(hwnd, es);
     986        break;
     987
     988    case WM_ENABLE:
     989        DPRINTF_EDIT_MSG32("WM_ENABLE");
    957990                es->bEnableState = (BOOL) wParam;
    958                 EDIT_UpdateText(hwnd, es, NULL, TRUE);
    959                 break;
    960 
    961         case WM_ERASEBKGND:
    962                 DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
    963                 result = EDIT_WM_EraseBkGnd(hwnd, es, (HDC)wParam);
    964                 break;
    965 
    966         case WM_GETFONT:
    967                 DPRINTF_EDIT_MSG32("WM_GETFONT");
    968                 result = (LRESULT)es->font;
    969                 break;
    970 
    971         case WM_GETTEXT:
    972                 DPRINTF_EDIT_MSG32("WM_GETTEXT");
    973                 result = (LRESULT)EDIT_WM_GetText(es, (INT)wParam, lParam, unicode);
    974                 break;
    975 
    976         case WM_GETTEXTLENGTH:
    977                 DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
    978                 result = strlenW(es->text);
    979                 break;
    980 
    981         case WM_HSCROLL:
    982                 DPRINTF_EDIT_MSG32("WM_HSCROLL");
    983                 result = EDIT_WM_HScroll(hwnd, es, LOWORD(wParam), SHIWORD(wParam));
    984                 break;
    985 
    986         case WM_KEYDOWN:
    987                 DPRINTF_EDIT_MSG32("WM_KEYDOWN");
    988                 result = EDIT_WM_KeyDown(hwnd, es, (INT)wParam);
    989                 break;
    990 
    991         case WM_KILLFOCUS:
    992                 DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
    993                 result = EDIT_WM_KillFocus(hwnd, es);
    994                 break;
    995 
    996         case WM_LBUTTONDBLCLK:
    997                 DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
    998                 result = EDIT_WM_LButtonDblClk(hwnd, es);
    999                 break;
    1000 
    1001         case WM_LBUTTONDOWN:
    1002                 DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
    1003                 result = EDIT_WM_LButtonDown(hwnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
    1004                 break;
    1005 
    1006         case WM_LBUTTONUP:
    1007                 DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
    1008                 result = EDIT_WM_LButtonUp(hwnd, es);
    1009                 break;
    1010 
    1011         case WM_MBUTTONDOWN:
    1012                 DPRINTF_EDIT_MSG32("WM_MBUTTONDOWN");
    1013                 result = EDIT_WM_MButtonDown(hwnd);
    1014                 break;
    1015 
    1016         case WM_MOUSEACTIVATE:
    1017                 /*
    1018                  *      FIXME: maybe DefWindowProc() screws up, but it seems that
    1019                  *              modeless dialog boxes need this.  If we don't do this, the focus
    1020                  *              will _not_ be set by DefWindowProc() for edit controls in a
    1021                  *              modeless dialog box ???
    1022                 */
    1023                 DPRINTF_EDIT_MSG32("WM_MOUSEACTIVATE");
    1024                 SetFocus(hwnd);
    1025                 result = MA_ACTIVATE;
    1026                 break;
    1027 
    1028         case WM_MOUSEMOVE:
    1029                 /*
    1030                  *      DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
    1031                 */
    1032                 result = EDIT_WM_MouseMove(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
    1033                 break;
    1034 
    1035         case WM_PAINT:
    1036                 DPRINTF_EDIT_MSG32("WM_PAINT");
    1037                 EDIT_WM_Paint(hwnd, es, wParam);
    1038                 break;
    1039 
    1040         case WM_PASTE:
    1041                 DPRINTF_EDIT_MSG32("WM_PASTE");
    1042                 EDIT_WM_Paste(hwnd, es);
    1043                 break;
    1044 
    1045         case WM_SETFOCUS:
    1046                 DPRINTF_EDIT_MSG32("WM_SETFOCUS");
    1047                 EDIT_WM_SetFocus(hwnd, es);
    1048                 break;
    1049 
    1050         case WM_SETFONT:
    1051                 DPRINTF_EDIT_MSG32("WM_SETFONT");
    1052                 EDIT_WM_SetFont(hwnd, es, (HFONT)wParam, LOWORD(lParam) != 0);
    1053                 break;
    1054 
    1055         case WM_SETREDRAW:
    1056                 /* FIXME: actually set an internal flag and behave accordingly */
    1057                 break;
    1058 
    1059         case WM_SETTEXT:
    1060                 DPRINTF_EDIT_MSG32("WM_SETTEXT");
    1061                 EDIT_WM_SetText(hwnd, es, lParam, unicode);
    1062                 result = TRUE;
    1063                 break;
    1064 
    1065         case WM_SIZE:
    1066                 DPRINTF_EDIT_MSG32("WM_SIZE");
    1067                 EDIT_WM_Size(hwnd, es, (UINT)wParam, LOWORD(lParam), HIWORD(lParam));
    1068                 break;
     991        EDIT_UpdateText(hwnd, es, NULL, TRUE);
     992        break;
     993
     994    case WM_ERASEBKGND:
     995        DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
     996        result = EDIT_WM_EraseBkGnd(hwnd, es, (HDC)wParam);
     997        break;
     998
     999    case WM_GETFONT:
     1000        DPRINTF_EDIT_MSG32("WM_GETFONT");
     1001        result = (LRESULT)es->font;
     1002        break;
     1003
     1004    case WM_GETTEXT:
     1005        DPRINTF_EDIT_MSG32("WM_GETTEXT");
     1006        result = (LRESULT)EDIT_WM_GetText(es, (INT)wParam, lParam, unicode);
     1007        break;
     1008
     1009    case WM_GETTEXTLENGTH:
     1010        DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
     1011        result = strlenW(es->text);
     1012        break;
     1013
     1014    case WM_HSCROLL:
     1015        DPRINTF_EDIT_MSG32("WM_HSCROLL");
     1016        result = EDIT_WM_HScroll(hwnd, es, LOWORD(wParam), SHIWORD(wParam));
     1017        break;
     1018
     1019    case WM_KEYDOWN:
     1020        DPRINTF_EDIT_MSG32("WM_KEYDOWN");
     1021        result = EDIT_WM_KeyDown(hwnd, es, (INT)wParam);
     1022        break;
     1023
     1024    case WM_KILLFOCUS:
     1025        DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
     1026        result = EDIT_WM_KillFocus(hwnd, es);
     1027        break;
     1028
     1029    case WM_LBUTTONDBLCLK:
     1030        DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
     1031        result = EDIT_WM_LButtonDblClk(hwnd, es);
     1032        break;
     1033
     1034    case WM_LBUTTONDOWN:
     1035        DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
     1036        result = EDIT_WM_LButtonDown(hwnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
     1037        break;
     1038
     1039    case WM_LBUTTONUP:
     1040        DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
     1041        result = EDIT_WM_LButtonUp(hwnd, es);
     1042        break;
     1043
     1044    case WM_MBUTTONDOWN:
     1045        DPRINTF_EDIT_MSG32("WM_MBUTTONDOWN");
     1046        result = EDIT_WM_MButtonDown(hwnd);
     1047        break;
     1048
     1049    case WM_MOUSEACTIVATE:
     1050        /*
     1051         *  FIXME: maybe DefWindowProc() screws up, but it seems that
     1052         *      modeless dialog boxes need this.  If we don't do this, the focus
     1053         *      will _not_ be set by DefWindowProc() for edit controls in a
     1054         *      modeless dialog box ???
     1055        */
     1056        DPRINTF_EDIT_MSG32("WM_MOUSEACTIVATE");
     1057        SetFocus(hwnd);
     1058        result = MA_ACTIVATE;
     1059        break;
     1060
     1061    case WM_MOUSEMOVE:
     1062        /*
     1063         *  DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
     1064        */
     1065        result = EDIT_WM_MouseMove(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
     1066        break;
     1067
     1068    case WM_PAINT:
     1069        DPRINTF_EDIT_MSG32("WM_PAINT");
     1070            EDIT_WM_Paint(hwnd, es, wParam);
     1071        break;
     1072
     1073    case WM_PASTE:
     1074        DPRINTF_EDIT_MSG32("WM_PASTE");
     1075        EDIT_WM_Paste(hwnd, es);
     1076        break;
     1077
     1078    case WM_SETFOCUS:
     1079        DPRINTF_EDIT_MSG32("WM_SETFOCUS");
     1080        EDIT_WM_SetFocus(hwnd, es);
     1081        break;
     1082
     1083    case WM_SETFONT:
     1084        DPRINTF_EDIT_MSG32("WM_SETFONT");
     1085        EDIT_WM_SetFont(hwnd, es, (HFONT)wParam, LOWORD(lParam) != 0);
     1086        break;
     1087
     1088    case WM_SETREDRAW:
     1089        /* FIXME: actually set an internal flag and behave accordingly */
     1090        break;
     1091
     1092    case WM_SETTEXT:
     1093        DPRINTF_EDIT_MSG32("WM_SETTEXT");
     1094        EDIT_WM_SetText(hwnd, es, lParam, unicode);
     1095        result = TRUE;
     1096        break;
     1097
     1098    case WM_SIZE:
     1099        DPRINTF_EDIT_MSG32("WM_SIZE");
     1100        EDIT_WM_Size(hwnd, es, (UINT)wParam, LOWORD(lParam), HIWORD(lParam));
     1101        break;
    10691102
    10701103        case WM_STYLECHANGED:
    1071                 DPRINTF_EDIT_MSG32("WM_STYLECHANGED");
     1104        DPRINTF_EDIT_MSG32("WM_STYLECHANGED");
    10721105                result = EDIT_WM_StyleChanged (hwnd, es, wParam, (const STYLESTRUCT *)lParam);
    10731106                break;
    10741107
    10751108        case WM_STYLECHANGING:
    1076                 DPRINTF_EDIT_MSG32("WM_STYLECHANGING");
     1109        DPRINTF_EDIT_MSG32("WM_STYLECHANGING");
    10771110                result = 0; /* See EDIT_WM_StyleChanged */
    10781111                break;
    10791112
    1080         case WM_SYSKEYDOWN:
    1081                 DPRINTF_EDIT_MSG32("WM_SYSKEYDOWN");
    1082                 result = EDIT_WM_SysKeyDown(hwnd, es, (INT)wParam, (DWORD)lParam);
    1083                 break;
    1084 
    1085         case WM_TIMER:
    1086                 DPRINTF_EDIT_MSG32("WM_TIMER");
    1087                 EDIT_WM_Timer(hwnd, es);
    1088                 break;
    1089 
    1090         case WM_VSCROLL:
    1091                 DPRINTF_EDIT_MSG32("WM_VSCROLL");
    1092                 result = EDIT_WM_VScroll(hwnd, es, LOWORD(wParam), SHIWORD(wParam));
    1093                 break;
     1113    case WM_SYSKEYDOWN:
     1114        DPRINTF_EDIT_MSG32("WM_SYSKEYDOWN");
     1115        result = EDIT_WM_SysKeyDown(hwnd, es, (INT)wParam, (DWORD)lParam);
     1116        break;
     1117
     1118    case WM_TIMER:
     1119        DPRINTF_EDIT_MSG32("WM_TIMER");
     1120        EDIT_WM_Timer(hwnd, es);
     1121        break;
     1122
     1123    case WM_VSCROLL:
     1124        DPRINTF_EDIT_MSG32("WM_VSCROLL");
     1125        result = EDIT_WM_VScroll(hwnd, es, LOWORD(wParam), SHIWORD(wParam));
     1126        break;
    10941127
    10951128        case WM_MOUSEWHEEL:
     
    11081141                        int cLineScroll= (int) min((UINT) es->line_count, pulScrollLines);
    11091142                        cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
    1110                         result = EDIT_EM_LineScroll(hwnd, es, 0, cLineScroll);
     1143            result = EDIT_EM_LineScroll(hwnd, es, 0, cLineScroll);
    11111144                    }
    11121145                }
    11131146                break;
    1114         default:
    1115                 if(unicode)
    1116                     result = DefWindowProcW(hwnd, msg, wParam, lParam);
    1117                 else
    1118                     result = DefWindowProcA(hwnd, msg, wParam, lParam);
    1119                 break;
    1120         }
    1121         EDIT_UnlockBuffer(hwnd, es, FALSE);
     1147    default:
     1148        if(unicode)
     1149            result = DefWindowProcW(hwnd, msg, wParam, lParam);
     1150        else
     1151            result = DefWindowProcA(hwnd, msg, wParam, lParam);
     1152        break;
     1153    }
     1154    EDIT_UnlockBuffer(hwnd, es, FALSE);
    11221155    END:
    1123         return result;
    1124 }
    1125 
    1126 /*********************************************************************
    1127  *
    1128  *      EditWndProcW   (USER32.@)
     1156    return result;
     1157}
     1158
     1159/*********************************************************************
     1160 *
     1161 *  EditWndProcW   (USER32.@)
    11291162 */
    11301163LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     
    11361169/*********************************************************************
    11371170 *
    1138  *      EditWndProc   (USER32.@)
     1171 *  EditWndProc   (USER32.@)
    11391172 */
    11401173LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     
    11461179/*********************************************************************
    11471180 *
    1148  *      EDIT_BuildLineDefs_ML
    1149  *
    1150  *      Build linked list of text lines.
    1151  *      Lines can end with '\0' (last line), a character (if it is wrapped),
    1152  *      a soft return '\r\r\n' or a hard return '\r\n'
     1181 *  EDIT_BuildLineDefs_ML
     1182 *
     1183 *  Build linked list of text lines.
     1184 *  Lines can end with '\0' (last line), a character (if it is wrapped),
     1185 *  a soft return '\r\r\n' or a hard return '\r\n'
    11531186 *
    11541187 */
    11551188static void EDIT_BuildLineDefs_ML(HWND hwnd, EDITSTATE *es, INT istart, INT iend, INT delta, HRGN hrgn)
    11561189{
    1157         HDC dc;
    1158         HFONT old_font = 0;
    1159         LPWSTR current_position, cp;
    1160         INT fw;
    1161         LINEDEF *current_line;
    1162         LINEDEF *previous_line;
    1163         LINEDEF *start_line;
    1164         INT line_index = 0, nstart_line = 0, nstart_index = 0;
    1165         INT line_count = es->line_count;
    1166         INT orig_net_length;
    1167         RECT rc;
    1168 
    1169         if (istart == iend && delta == 0)
    1170                 return;
    1171 
    1172         dc = GetDC(hwnd);
    1173         if (es->font)
    1174                 old_font = SelectObject(dc, es->font);
    1175 
    1176         previous_line = NULL;
    1177         current_line = es->first_line_def;
    1178 
    1179         /* Find starting line. istart must lie inside an existing line or
    1180         * at the end of buffer */
    1181         do {
    1182                 if (istart < current_line->index + current_line->length ||
    1183                                 current_line->ending == END_0)
    1184                         break;
    1185 
    1186                 previous_line = current_line;
    1187                 current_line = current_line->next;
    1188                 line_index++;
    1189         } while (current_line);
    1190 
    1191         if (!current_line) /* Error occurred start is not inside previous buffer */
    1192         {
    1193                 FIXME(" modification occurred outside buffer\n");
    1194                 return;
    1195         }
    1196 
    1197         /* Remember start of modifications in order to calculate update region */
    1198         nstart_line = line_index;
    1199         nstart_index = current_line->index;
    1200 
    1201         /* We must start to reformat from the previous line since the modifications
    1202         * may have caused the line to wrap upwards. */
    1203         if (!(es->style & ES_AUTOHSCROLL) && line_index > 0)
    1204         {
    1205                 line_index--;
    1206                 current_line = previous_line;
    1207         }
    1208         start_line = current_line;
    1209 
    1210         fw = es->format_rect.right - es->format_rect.left;
    1211         current_position = es->text + current_line->index;
    1212         do {
    1213                 if (current_line != start_line)
    1214                 {
    1215                         if (!current_line || current_line->index + delta > current_position - es->text)
    1216                         {
    1217                                 /* The buffer has been expanded, create a new line and
    1218                                    insert it into the link list */
    1219                                 LINEDEF *new_line = HeapAlloc(GetProcessHeap(), 0, sizeof(LINEDEF));
    1220                                 new_line->next = previous_line->next;
    1221                                 previous_line->next = new_line;
    1222                                 current_line = new_line;
    1223                                 es->line_count++;
    1224                         }
    1225                         else if (current_line->index + delta < current_position - es->text)
    1226                         {
    1227                                 /* The previous line merged with this line so we delete this extra entry */
    1228                                 previous_line->next = current_line->next;
    1229                                 HeapFree(GetProcessHeap(), 0, current_line);
    1230                                 current_line = previous_line->next;
    1231                                 es->line_count--;
    1232                                 continue;
    1233                         }
    1234                         else /* current_line->index + delta == current_position */
    1235                         {
    1236                                 if (current_position - es->text > iend)
    1237                                         break; /* We reached end of line modifications */
    1238                                 /* else recalulate this line */
    1239                         }
    1240                 }
    1241 
    1242                 current_line->index = current_position - es->text;
    1243                 orig_net_length = current_line->net_length;
    1244 
    1245                 /* Find end of line */
    1246                 cp = current_position;
    1247                 while (*cp) {
    1248                         if ((*cp == '\r') && (*(cp + 1) == '\n'))
    1249                                 break;
    1250                         cp++;
    1251                 }
    1252 
    1253                 /* Mark type of line termination */
    1254                 if (!(*cp)) {
    1255                         current_line->ending = END_0;
    1256                         current_line->net_length = strlenW(current_position);
    1257                 } else if ((cp > current_position) && (*(cp - 1) == '\r')) {
    1258                         current_line->ending = END_SOFT;
    1259                         current_line->net_length = cp - current_position - 1;
    1260                 } else {
    1261                         current_line->ending = END_HARD;
    1262                         current_line->net_length = cp - current_position;
    1263                 }
    1264 
    1265                 /* Calculate line width */
    1266                 current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
    1267                                         current_position, current_line->net_length,
    1268                                         es->tabs_count, es->tabs));
    1269 
    1270                 /* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 32767 ???) */
    1271                 if ((!(es->style & ES_AUTOHSCROLL)) && (current_line->width > fw)) {
    1272                         INT next = 0;
    1273                         INT prev;
    1274                         do {
    1275                                 prev = next;
    1276                                 next = EDIT_CallWordBreakProc(es, current_position - es->text,
    1277                                                 prev + 1, current_line->net_length, WB_RIGHT);
    1278                                 current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
    1279                                                         current_position, next, es->tabs_count, es->tabs));
    1280                         } while (current_line->width <= fw);
    1281                         if (!prev) { /* Didn't find a line break so force a break */
    1282                                 next = 0;
    1283                                 do {
    1284                                         prev = next;
    1285                                         next++;
    1286                                         current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
    1287                                                                 current_position, next, es->tabs_count, es->tabs));
    1288                                 } while (current_line->width <= fw);
    1289                                 if (!prev)
    1290                                         prev = 1;
    1291                         }
    1292 
    1293                         /* If the first line we are calculating, wrapped before istart, we must
    1294                         * adjust istart in order for this to be reflected in the update region. */
    1295                         if (current_line->index == nstart_index && istart > current_line->index + prev)
    1296                                 istart = current_line->index + prev;
    1297                         /* else if we are updating the previous line before the first line we
    1298                         * are re-calculating and it expanded */
    1299                         else if (current_line == start_line &&
    1300                                         current_line->index != nstart_index && orig_net_length < prev)
    1301                         {
    1302                           /* Line expanded due to an upwards line wrap so we must partially include
    1303                            * previous line in update region */
    1304                                 nstart_line = line_index;
    1305                                 nstart_index = current_line->index;
    1306                                 istart = current_line->index + orig_net_length;
    1307                         }
    1308 
    1309                         current_line->net_length = prev;
    1310                         current_line->ending = END_WRAP;
    1311                         current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc, current_position,
    1312                                         current_line->net_length, es->tabs_count, es->tabs));
    1313                 }
    1314 
    1315 
    1316                 /* Adjust length to include line termination */
    1317                 switch (current_line->ending) {
    1318                 case END_SOFT:
    1319                         current_line->length = current_line->net_length + 3;
    1320                         break;
    1321                 case END_HARD:
    1322                         current_line->length = current_line->net_length + 2;
    1323                         break;
    1324                 case END_WRAP:
    1325                 case END_0:
    1326                         current_line->length = current_line->net_length;
    1327                         break;
    1328                 }
    1329                 es->text_width = max(es->text_width, current_line->width);
    1330                 current_position += current_line->length;
    1331                 previous_line = current_line;
    1332                 current_line = current_line->next;
    1333                 line_index++;
    1334         } while (previous_line->ending != END_0);
    1335 
    1336         /* Finish adjusting line indexes by delta or remove hanging lines */
    1337         if (previous_line->ending == END_0)
    1338         {
    1339                 LINEDEF *pnext = NULL;
    1340 
    1341                 previous_line->next = NULL;
    1342                 while (current_line)
    1343                 {
    1344                         pnext = current_line->next;
    1345                         HeapFree(GetProcessHeap(), 0, current_line);
    1346                         current_line = pnext;
    1347                         es->line_count--;
    1348                 }
    1349         }
    1350         else
    1351         {
    1352                 while (current_line)
    1353                 {
    1354                         current_line->index += delta;
    1355                         current_line = current_line->next;
    1356                 }
    1357         }
    1358 
    1359         /* Calculate rest of modification rectangle */
    1360         if (hrgn)
    1361         {
    1362                 HRGN tmphrgn;
    1363            /*
    1364                 * We calculate two rectangles. One for the first line which may have
    1365                 * an indent with respect to the format rect. The other is a format-width
    1366                 * rectangle that spans the rest of the lines that changed or moved.
    1367                 */
    1368                 rc.top = es->format_rect.top + nstart_line * es->line_height -
    1369                         (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
    1370                 rc.bottom = rc.top + es->line_height;
    1371                 rc.left = es->format_rect.left + (INT)LOWORD(GetTabbedTextExtentW(dc,
    1372                                         es->text + nstart_index, istart - nstart_index,
    1373                                         es->tabs_count, es->tabs)) - es->x_offset; /* Adjust for horz scroll */
    1374                 rc.right = es->format_rect.right;
    1375                 SetRectRgn(hrgn, rc.left, rc.top, rc.right, rc.bottom);
    1376 
    1377                 rc.top = rc.bottom;
    1378                 rc.left = es->format_rect.left;
    1379                 rc.right = es->format_rect.right;
    1380            /*
    1381                 * If lines were added or removed we must re-paint the remainder of the
    1382             * lines since the remaining lines were either shifted up or down.
    1383                 */
    1384                 if (line_count < es->line_count) /* We added lines */
    1385                         rc.bottom = es->line_count * es->line_height;
    1386                 else if (line_count > es->line_count) /* We removed lines */
    1387                         rc.bottom = line_count * es->line_height;
    1388                 else
    1389                         rc.bottom = line_index * es->line_height;
    1390                 rc.bottom -= (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
    1391                 tmphrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
    1392                 CombineRgn(hrgn, hrgn, tmphrgn, RGN_OR);
    1393                 DeleteObject(tmphrgn);
    1394         }
    1395 
    1396         if (es->font)
    1397                 SelectObject(dc, old_font);
    1398 
    1399         ReleaseDC(hwnd, dc);
    1400 }
    1401 
    1402 /*********************************************************************
    1403  *
    1404  *      EDIT_CalcLineWidth_SL
     1190    HDC dc;
     1191    HFONT old_font = 0;
     1192    LPWSTR current_position, cp;
     1193    INT fw;
     1194    LINEDEF *current_line;
     1195    LINEDEF *previous_line;
     1196    LINEDEF *start_line;
     1197    INT line_index = 0, nstart_line = 0, nstart_index = 0;
     1198    INT line_count = es->line_count;
     1199    INT orig_net_length;
     1200    RECT rc;
     1201
     1202    if (istart == iend && delta == 0)
     1203        return;
     1204
     1205    dc = GetDC(hwnd);
     1206    if (es->font)
     1207        old_font = SelectObject(dc, es->font);
     1208
     1209    previous_line = NULL;
     1210    current_line = es->first_line_def;
     1211
     1212    /* Find starting line. istart must lie inside an existing line or
     1213    * at the end of buffer */
     1214    do {
     1215        if (istart < current_line->index + current_line->length ||
     1216                current_line->ending == END_0)
     1217            break;
     1218
     1219        previous_line = current_line;
     1220        current_line = current_line->next;
     1221        line_index++;
     1222    } while (current_line);
     1223
     1224    if (!current_line) /* Error occurred start is not inside previous buffer */
     1225    {
     1226        FIXME(" modification occurred outside buffer\n");
     1227        return;
     1228    }
     1229
     1230    /* Remember start of modifications in order to calculate update region */
     1231    nstart_line = line_index;
     1232    nstart_index = current_line->index;
     1233
     1234    /* We must start to reformat from the previous line since the modifications
     1235    * may have caused the line to wrap upwards. */
     1236    if (!(es->style & ES_AUTOHSCROLL) && line_index > 0)
     1237    {
     1238        line_index--;
     1239        current_line = previous_line;
     1240    }
     1241    start_line = current_line;
     1242
     1243    fw = es->format_rect.right - es->format_rect.left;
     1244    current_position = es->text + current_line->index;
     1245    do {
     1246        if (current_line != start_line)
     1247        {
     1248            if (!current_line || current_line->index + delta > current_position - es->text)
     1249            {
     1250                /* The buffer has been expanded, create a new line and
     1251                   insert it into the link list */
     1252                LINEDEF *new_line = HeapAlloc(GetProcessHeap(), 0, sizeof(LINEDEF));
     1253                new_line->next = previous_line->next;
     1254                previous_line->next = new_line;
     1255                current_line = new_line;
     1256                es->line_count++;
     1257            }
     1258            else if (current_line->index + delta < current_position - es->text)
     1259            {
     1260                /* The previous line merged with this line so we delete this extra entry */
     1261                previous_line->next = current_line->next;
     1262                HeapFree(GetProcessHeap(), 0, current_line);
     1263                current_line = previous_line->next;
     1264                es->line_count--;
     1265                continue;
     1266            }
     1267            else /* current_line->index + delta == current_position */
     1268            {
     1269                if (current_position - es->text > iend)
     1270                    break; /* We reached end of line modifications */
     1271                /* else recalulate this line */
     1272            }
     1273        }
     1274
     1275        current_line->index = current_position - es->text;
     1276        orig_net_length = current_line->net_length;
     1277
     1278        /* Find end of line */
     1279        cp = current_position;
     1280        while (*cp) {
     1281            if ((*cp == '\r') && (*(cp + 1) == '\n'))
     1282                break;
     1283            cp++;
     1284        }
     1285
     1286        /* Mark type of line termination */
     1287        if (!(*cp)) {
     1288            current_line->ending = END_0;
     1289            current_line->net_length = strlenW(current_position);
     1290        } else if ((cp > current_position) && (*(cp - 1) == '\r')) {
     1291            current_line->ending = END_SOFT;
     1292            current_line->net_length = cp - current_position - 1;
     1293        } else {
     1294            current_line->ending = END_HARD;
     1295            current_line->net_length = cp - current_position;
     1296        }
     1297
     1298        /* Calculate line width */
     1299        current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
     1300                    current_position, current_line->net_length,
     1301                    es->tabs_count, es->tabs));
     1302
     1303        /* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 32767 ???) */
     1304        if ((!(es->style & ES_AUTOHSCROLL)) && (current_line->width > fw)) {
     1305            INT next = 0;
     1306            INT prev;
     1307            do {
     1308                prev = next;
     1309                next = EDIT_CallWordBreakProc(es, current_position - es->text,
     1310                        prev + 1, current_line->net_length, WB_RIGHT);
     1311                current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
     1312                            current_position, next, es->tabs_count, es->tabs));
     1313            } while (current_line->width <= fw);
     1314            if (!prev) { /* Didn't find a line break so force a break */
     1315                next = 0;
     1316                do {
     1317                    prev = next;
     1318                    next++;
     1319                    current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc,
     1320                                current_position, next, es->tabs_count, es->tabs));
     1321                } while (current_line->width <= fw);
     1322                if (!prev)
     1323                    prev = 1;
     1324            }
     1325
     1326            /* If the first line we are calculating, wrapped before istart, we must
     1327            * adjust istart in order for this to be reflected in the update region. */
     1328            if (current_line->index == nstart_index && istart > current_line->index + prev)
     1329                istart = current_line->index + prev;
     1330            /* else if we are updating the previous line before the first line we
     1331            * are re-calculating and it expanded */
     1332            else if (current_line == start_line &&
     1333                    current_line->index != nstart_index && orig_net_length < prev)
     1334            {
     1335              /* Line expanded due to an upwards line wrap so we must partially include
     1336               * previous line in update region */
     1337                nstart_line = line_index;
     1338                nstart_index = current_line->index;
     1339                istart = current_line->index + orig_net_length;
     1340            }
     1341
     1342            current_line->net_length = prev;
     1343            current_line->ending = END_WRAP;
     1344            current_line->width = (INT)LOWORD(GetTabbedTextExtentW(dc, current_position,
     1345                    current_line->net_length, es->tabs_count, es->tabs));
     1346        }
     1347
     1348
     1349        /* Adjust length to include line termination */
     1350        switch (current_line->ending) {
     1351        case END_SOFT:
     1352            current_line->length = current_line->net_length + 3;
     1353            break;
     1354        case END_HARD:
     1355            current_line->length = current_line->net_length + 2;
     1356            break;
     1357        case END_WRAP:
     1358        case END_0:
     1359            current_line->length = current_line->net_length;
     1360            break;
     1361        }
     1362        es->text_width = max(es->text_width, current_line->width);
     1363        current_position += current_line->length;
     1364        previous_line = current_line;
     1365        current_line = current_line->next;
     1366        line_index++;
     1367    } while (previous_line->ending != END_0);
     1368
     1369    /* Finish adjusting line indexes by delta or remove hanging lines */
     1370    if (previous_line->ending == END_0)
     1371    {
     1372        LINEDEF *pnext = NULL;
     1373
     1374        previous_line->next = NULL;
     1375        while (current_line)
     1376        {
     1377            pnext = current_line->next;
     1378            HeapFree(GetProcessHeap(), 0, current_line);
     1379            current_line = pnext;
     1380            es->line_count--;
     1381        }
     1382    }
     1383    else
     1384    {
     1385        while (current_line)
     1386        {
     1387            current_line->index += delta;
     1388            current_line = current_line->next;
     1389        }
     1390    }
     1391
     1392    /* Calculate rest of modification rectangle */
     1393    if (hrgn)
     1394    {
     1395        HRGN tmphrgn;
     1396       /*
     1397        * We calculate two rectangles. One for the first line which may have
     1398        * an indent with respect to the format rect. The other is a format-width
     1399        * rectangle that spans the rest of the lines that changed or moved.
     1400        */
     1401        rc.top = es->format_rect.top + nstart_line * es->line_height -
     1402            (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
     1403        rc.bottom = rc.top + es->line_height;
     1404        rc.left = es->format_rect.left + (INT)LOWORD(GetTabbedTextExtentW(dc,
     1405                    es->text + nstart_index, istart - nstart_index,
     1406                    es->tabs_count, es->tabs)) - es->x_offset; /* Adjust for horz scroll */
     1407        rc.right = es->format_rect.right;
     1408        SetRectRgn(hrgn, rc.left, rc.top, rc.right, rc.bottom);
     1409
     1410        rc.top = rc.bottom;
     1411        rc.left = es->format_rect.left;
     1412        rc.right = es->format_rect.right;
     1413       /*
     1414        * If lines were added or removed we must re-paint the remainder of the
     1415        * lines since the remaining lines were either shifted up or down.
     1416        */
     1417        if (line_count < es->line_count) /* We added lines */
     1418            rc.bottom = es->line_count * es->line_height;
     1419        else if (line_count > es->line_count) /* We removed lines */
     1420            rc.bottom = line_count * es->line_height;
     1421        else
     1422            rc.bottom = line_index * es->line_height;
     1423        rc.bottom -= (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
     1424        tmphrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
     1425        CombineRgn(hrgn, hrgn, tmphrgn, RGN_OR);
     1426        DeleteObject(tmphrgn);
     1427    }
     1428
     1429    if (es->font)
     1430        SelectObject(dc, old_font);
     1431
     1432    ReleaseDC(hwnd, dc);
     1433}
     1434
     1435/*********************************************************************
     1436 *
     1437 *  EDIT_CalcLineWidth_SL
    14051438 *
    14061439 */
     
    14121445/*********************************************************************
    14131446 *
    1414  *      EDIT_CallWordBreakProc
    1415  *
    1416  *      Call appropriate WordBreakProc (internal or external).
    1417  *
    1418  *      Note: The "start" argument should always be an index referring
    1419  *              to es->text.  The actual wordbreak proc might be
    1420  *              16 bit, so we can't always pass any 32 bit LPSTR.
    1421  *              Hence we assume that es->text is the buffer that holds
    1422  *              the string under examination (we can decide this for ourselves).
     1447 *  EDIT_CallWordBreakProc
     1448 *
     1449 *  Call appropriate WordBreakProc (internal or external).
     1450 *
     1451 *  Note: The "start" argument should always be an index referring
     1452 *      to es->text.  The actual wordbreak proc might be
     1453 *      16 bit, so we can't always pass any 32 bit LPSTR.
     1454 *      Hence we assume that es->text is the buffer that holds
     1455 *      the string under examination (we can decide this for ourselves).
    14231456 *
    14241457 */
     
    14351468
    14361469#ifndef __WIN32OS2__
    1437         if (es->word_break_proc16) {
    1438             HGLOBAL16 hglob16;
    1439             SEGPTR segptr;
    1440             INT countA;
    1441 
    1442             countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
    1443             hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
    1444             segptr = K32WOWGlobalLock16(hglob16);
    1445             WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
    1446             ret = (INT)EDIT_CallTo16_word_lwww(es->word_break_proc16,
    1447                                                 segptr, index, countA, action);
    1448             GlobalUnlock16(hglob16);
    1449             GlobalFree16(hglob16);
    1450         }
    1451         else
     1470    if (es->word_break_proc16) {
     1471        HGLOBAL16 hglob16;
     1472        SEGPTR segptr;
     1473        INT countA;
     1474
     1475        countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
     1476        hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
     1477        segptr = K32WOWGlobalLock16(hglob16);
     1478        WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
     1479        ret = (INT)EDIT_CallTo16_word_lwww(es->word_break_proc16,
     1480                        segptr, index, countA, action);
     1481        GlobalUnlock16(hglob16);
     1482        GlobalFree16(hglob16);
     1483    }
     1484    else
    14521485#endif
    14531486        if (es->word_break_proc)
    14541487        {
    1455             if(es->is_unicode)
    1456             {
    1457                 EDITWORDBREAKPROCW wbpW = (EDITWORDBREAKPROCW)es->word_break_proc;
    1458 
    1459                 TRACE_(relay)("(UNICODE wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
    1460                         es->word_break_proc, debugstr_wn(es->text + start, count), index, count, action);
    1461                 ret = wbpW(es->text + start, index, count, action);
    1462             }
    1463             else
    1464             {
    1465                 EDITWORDBREAKPROCA wbpA = (EDITWORDBREAKPROCA)es->word_break_proc;
    1466                 INT countA;
    1467                 CHAR *textA;
    1468 
    1469                 countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
    1470                 textA = HeapAlloc(GetProcessHeap(), 0, countA);
    1471                 WideCharToMultiByte(CP_ACP, 0, es->text + start, count, textA, countA, NULL, NULL);
    1472                 TRACE_(relay)("(ANSI wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
    1473                         es->word_break_proc, debugstr_an(textA, countA), index, countA, action);
    1474                 ret = wbpA(textA, index, countA, action);
    1475                 HeapFree(GetProcessHeap(), 0, textA);
    1476             }
    1477         }
    1478         else
     1488        if(es->is_unicode)
     1489        {
     1490        EDITWORDBREAKPROCW wbpW = (EDITWORDBREAKPROCW)es->word_break_proc;
     1491
     1492        TRACE_(relay)("(UNICODE wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
     1493            es->word_break_proc, debugstr_wn(es->text + start, count), index, count, action);
     1494        ret = wbpW(es->text + start, index, count, action);
     1495        }
     1496        else
     1497        {
     1498        EDITWORDBREAKPROCA wbpA = (EDITWORDBREAKPROCA)es->word_break_proc;
     1499        INT countA;
     1500        CHAR *textA;
     1501
     1502        countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
     1503        textA = HeapAlloc(GetProcessHeap(), 0, countA);
     1504        WideCharToMultiByte(CP_ACP, 0, es->text + start, count, textA, countA, NULL, NULL);
     1505        TRACE_(relay)("(ANSI wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
     1506            es->word_break_proc, debugstr_an(textA, countA), index, countA, action);
     1507        ret = wbpA(textA, index, countA, action);
     1508        HeapFree(GetProcessHeap(), 0, textA);
     1509        }
     1510        }
     1511    else
    14791512            ret = EDIT_WordBreakProc(es->text + start, index, count, action);
    14801513
     
    14861519/*********************************************************************
    14871520 *
    1488  *      EDIT_CharFromPos
    1489  *
    1490  *      Beware: This is not the function called on EM_CHARFROMPOS
    1491  *              The position _can_ be outside the formatting / client
    1492  *              rectangle
    1493  *              The return value is only the character index
     1521 *  EDIT_CharFromPos
     1522 *
     1523 *  Beware: This is not the function called on EM_CHARFROMPOS
     1524 *      The position _can_ be outside the formatting / client
     1525 *      rectangle
     1526 *      The return value is only the character index
    14941527 *
    14951528 */
    14961529static INT EDIT_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
    14971530{
    1498         INT index;
    1499         HDC dc;
    1500         HFONT old_font = 0;
    1501 
    1502         if (es->style & ES_MULTILINE) {
    1503                 INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
    1504                 INT line_index = 0;
    1505                 LINEDEF *line_def = es->first_line_def;
    1506                 INT low, high;
    1507                 while ((line > 0) && line_def->next) {
    1508                         line_index += line_def->length;
    1509                         line_def = line_def->next;
    1510                         line--;
    1511                 }
    1512                 x += es->x_offset - es->format_rect.left;
    1513                 if (x >= line_def->width) {
    1514                         if (after_wrap)
    1515                                 *after_wrap = (line_def->ending == END_WRAP);
    1516                         return line_index + line_def->net_length;
    1517                 }
    1518                 if (x <= 0) {
    1519                         if (after_wrap)
    1520                                 *after_wrap = FALSE;
    1521                         return line_index;
    1522                 }
    1523                 dc = GetDC(hwnd);
    1524                 if (es->font)
    1525                         old_font = SelectObject(dc, es->font);
     1531    INT index;
     1532    HDC dc;
     1533    HFONT old_font = 0;
     1534
     1535    if (es->style & ES_MULTILINE) {
     1536        INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
     1537        INT line_index = 0;
     1538        LINEDEF *line_def = es->first_line_def;
     1539        INT low, high;
     1540        while ((line > 0) && line_def->next) {
     1541            line_index += line_def->length;
     1542            line_def = line_def->next;
     1543            line--;
     1544        }
     1545        x += es->x_offset - es->format_rect.left;
     1546        if (x >= line_def->width) {
     1547            if (after_wrap)
     1548                *after_wrap = (line_def->ending == END_WRAP);
     1549            return line_index + line_def->net_length;
     1550        }
     1551        if (x <= 0) {
     1552            if (after_wrap)
     1553                *after_wrap = FALSE;
     1554            return line_index;
     1555        }
     1556        dc = GetDC(hwnd);
     1557        if (es->font)
     1558            old_font = SelectObject(dc, es->font);
    15261559                    low = line_index + 1;
    15271560                    high = line_index + line_def->net_length + 1;
     
    15291562                    {
    15301563                        INT mid = (low + high) / 2;
    1531                         if (LOWORD(GetTabbedTextExtentW(dc, es->text + line_index,mid - line_index, es->tabs_count, es->tabs)) > x) high = mid;
     1564            if (LOWORD(GetTabbedTextExtentW(dc, es->text + line_index,mid - line_index, es->tabs_count, es->tabs)) > x) high = mid;
    15321565                        else low = mid;
    15331566                    }
    15341567                    index = low;
    15351568
    1536                 if (after_wrap)
    1537                         *after_wrap = ((index == line_index + line_def->net_length) &&
    1538                                                         (line_def->ending == END_WRAP));
    1539         } else {
    1540                 LPWSTR text;
    1541                 SIZE size;
    1542                 if (after_wrap)
    1543                         *after_wrap = FALSE;
    1544                 x -= es->format_rect.left;
    1545                 if (!x)
    1546                         return es->x_offset;
    1547                 text = EDIT_GetPasswordPointer_SL(es);
    1548                 dc = GetDC(hwnd);
    1549                 if (es->font)
    1550                         old_font = SelectObject(dc, es->font);
    1551                 if (x < 0)
     1569        if (after_wrap)
     1570            *after_wrap = ((index == line_index + line_def->net_length) &&
     1571                            (line_def->ending == END_WRAP));
     1572    } else {
     1573        LPWSTR text;
     1574        SIZE size;
     1575        if (after_wrap)
     1576            *after_wrap = FALSE;
     1577        x -= es->format_rect.left;
     1578        if (!x)
     1579            return es->x_offset;
     1580        text = EDIT_GetPasswordPointer_SL(es);
     1581        dc = GetDC(hwnd);
     1582        if (es->font)
     1583            old_font = SelectObject(dc, es->font);
     1584        if (x < 0)
    15521585                {
    15531586                    INT low = 0;
     
    15621595                    }
    15631596                    index = low;
    1564                 }
     1597        }
    15651598                else
    15661599                {
     
    15761609                    }
    15771610                    index = low;
    1578                 }
    1579                 if (es->style & ES_PASSWORD)
    1580                         HeapFree(GetProcessHeap(), 0, text);
    1581         }
    1582         if (es->font)
    1583                 SelectObject(dc, old_font);
    1584         ReleaseDC(hwnd, dc);
    1585         return index;
    1586 }
    1587 
    1588 
    1589 /*********************************************************************
    1590  *
    1591  *      EDIT_ConfinePoint
    1592  *
    1593  *      adjusts the point to be within the formatting rectangle
    1594  *      (so CharFromPos returns the nearest _visible_ character)
     1611        }
     1612        if (es->style & ES_PASSWORD)
     1613            HeapFree(GetProcessHeap(), 0, text);
     1614    }
     1615    if (es->font)
     1616        SelectObject(dc, old_font);
     1617    ReleaseDC(hwnd, dc);
     1618    return index;
     1619}
     1620
     1621
     1622/*********************************************************************
     1623 *
     1624 *  EDIT_ConfinePoint
     1625 *
     1626 *  adjusts the point to be within the formatting rectangle
     1627 *  (so CharFromPos returns the nearest _visible_ character)
    15951628 *
    15961629 */
    15971630static void EDIT_ConfinePoint(EDITSTATE *es, LPINT x, LPINT y)
    15981631{
    1599         *x = min(max(*x, es->format_rect.left), es->format_rect.right - 1);
    1600         *y = min(max(*y, es->format_rect.top), es->format_rect.bottom - 1);
    1601 }
    1602 
    1603 
    1604 /*********************************************************************
    1605  *
    1606  *      EDIT_GetLineRect
    1607  *
    1608  *      Calculates the bounding rectangle for a line from a starting
    1609  *      column to an ending column.
     1632    *x = min(max(*x, es->format_rect.left), es->format_rect.right - 1);
     1633    *y = min(max(*y, es->format_rect.top), es->format_rect.bottom - 1);
     1634}
     1635
     1636
     1637/*********************************************************************
     1638 *
     1639 *  EDIT_GetLineRect
     1640 *
     1641 *  Calculates the bounding rectangle for a line from a starting
     1642 *  column to an ending column.
    16101643 *
    16111644 */
    16121645static void EDIT_GetLineRect(HWND hwnd, EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
    16131646{
    1614         INT line_index =  EDIT_EM_LineIndex(es, line);
    1615 
    1616         if (es->style & ES_MULTILINE)
    1617                 rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
    1618         else
    1619                 rc->top = es->format_rect.top;
    1620         rc->bottom = rc->top + es->line_height;
    1621         rc->left = (scol == 0) ? es->format_rect.left : SLOWORD(EDIT_EM_PosFromChar(hwnd, es, line_index + scol, TRUE));
    1622         rc->right = (ecol == -1) ? es->format_rect.right : SLOWORD(EDIT_EM_PosFromChar(hwnd, es, line_index + ecol, TRUE));
    1623 }
    1624 
    1625 
    1626 /*********************************************************************
    1627  *
    1628  *      EDIT_GetPasswordPointer_SL
    1629  *
    1630  *      note: caller should free the (optionally) allocated buffer
     1647    INT line_index =  EDIT_EM_LineIndex(es, line);
     1648
     1649    if (es->style & ES_MULTILINE)
     1650        rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
     1651    else
     1652        rc->top = es->format_rect.top;
     1653    rc->bottom = rc->top + es->line_height;
     1654    rc->left = (scol == 0) ? es->format_rect.left : SLOWORD(EDIT_EM_PosFromChar(hwnd, es, line_index + scol, TRUE));
     1655    rc->right = (ecol == -1) ? es->format_rect.right : SLOWORD(EDIT_EM_PosFromChar(hwnd, es, line_index + ecol, TRUE));
     1656}
     1657
     1658
     1659/*********************************************************************
     1660 *
     1661 *  EDIT_GetPasswordPointer_SL
     1662 *
     1663 *  note: caller should free the (optionally) allocated buffer
    16311664 *
    16321665 */
    16331666static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
    16341667{
    1635         if (es->style & ES_PASSWORD) {
    1636                 INT len = strlenW(es->text);
    1637                 LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
    1638                 text[len] = '\0';
    1639                 while(len) text[--len] = es->password_char;
    1640                 return text;
    1641         } else
    1642                 return es->text;
    1643 }
    1644 
    1645 
    1646 /*********************************************************************
    1647  *
    1648  *      EDIT_LockBuffer
    1649  *
    1650  *      This acts as a LOCAL_Lock(), but it locks only once.  This way
    1651  *      you can call it whenever you like, without unlocking.
     1668    if (es->style & ES_PASSWORD) {
     1669        INT len = strlenW(es->text);
     1670        LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
     1671        text[len] = '\0';
     1672        while(len) text[--len] = es->password_char;
     1673        return text;
     1674    } else
     1675        return es->text;
     1676}
     1677
     1678
     1679/*********************************************************************
     1680 *
     1681 *  EDIT_LockBuffer
     1682 *
     1683 *  This acts as a LOCAL_Lock(), but it locks only once.  This way
     1684 *  you can call it whenever you like, without unlocking.
    16521685 *
    16531686 */
     
    16551688{
    16561689    HINSTANCE hInstance = GetWindowLongA( hwnd, GWL_HINSTANCE );
    1657         if (!es) {
    1658                 ERR("no EDITSTATE ... please report\n");
    1659                 return;
    1660         }
    1661         if (!es->text) {
    1662             CHAR *textA = NULL;
    1663             UINT countA = 0;
    1664             BOOL _16bit = FALSE;
    1665 
    1666             if(es->hloc32W)
    1667             {
    1668                 if(es->hloc32A)
    1669                 {
    1670                     TRACE("Synchronizing with 32-bit ANSI buffer\n");
    1671                     textA = LocalLock(es->hloc32A);
    1672                     countA = strlen(textA) + 1;
    1673                 }
    1674                 else if(es->hloc16)
    1675                 {
    1676                     TRACE("Synchronizing with 16-bit ANSI buffer\n");
    1677                     textA = LOCAL_Lock(hInstance, es->hloc16);
    1678                     countA = strlen(textA) + 1;
    1679                     _16bit = TRUE;
    1680                 }
    1681             }
    1682             else {
    1683                 ERR("no buffer ... please report\n");
    1684                 return;
    1685             }
    1686 
    1687             if(textA)
    1688             {
    1689                 HLOCAL hloc32W_new;
    1690                 UINT countW_new = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
    1691                 TRACE("%d bytes translated to %d WCHARs\n", countA, countW_new);
    1692                 if(countW_new > es->buffer_size + 1)
    1693                 {
    1694                     UINT alloc_size = ROUND_TO_GROW(countW_new * sizeof(WCHAR));
    1695                     TRACE("Resizing 32-bit UNICODE buffer from %d+1 to %d WCHARs\n", es->buffer_size, countW_new);
    1696                     hloc32W_new = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
    1697                     if(hloc32W_new)
    1698                     {
    1699                         es->hloc32W = hloc32W_new;
    1700                         es->buffer_size = LocalSize(hloc32W_new)/sizeof(WCHAR) - 1;
    1701                         TRACE("Real new size %d+1 WCHARs\n", es->buffer_size);
    1702                     }
    1703                     else
    1704                         WARN("FAILED! Will synchronize partially\n");
    1705                 }
    1706             }
    1707 
    1708             /*TRACE("Locking 32-bit UNICODE buffer\n");*/
    1709             es->text = LocalLock(es->hloc32W);
    1710 
    1711             if(textA)
    1712             {
    1713                 MultiByteToWideChar(CP_ACP, 0, textA, countA, es->text, es->buffer_size + 1);
    1714                 if(_16bit)
    1715                     LOCAL_Unlock(hInstance, es->hloc16);
    1716                 else
    1717                     LocalUnlock(es->hloc32A);
    1718             }
    1719         }
    1720         es->lock_count++;
    1721 }
    1722 
    1723 
    1724 /*********************************************************************
    1725  *
    1726  *      EDIT_SL_InvalidateText
    1727  *
    1728  *      Called from EDIT_InvalidateText().
    1729  *      Does the job for single-line controls only.
     1690    if (!es) {
     1691        ERR("no EDITSTATE ... please report\n");
     1692        return;
     1693    }
     1694    if (!es->text) {
     1695        CHAR *textA = NULL;
     1696        UINT countA = 0;
     1697        BOOL _16bit = FALSE;
     1698
     1699        if(es->hloc32W)
     1700        {
     1701        if(es->hloc32A)
     1702        {
     1703            TRACE("Synchronizing with 32-bit ANSI buffer\n");
     1704            textA = LocalLock(es->hloc32A);
     1705            countA = strlen(textA) + 1;
     1706        }
     1707        else if(es->hloc16)
     1708        {
     1709            TRACE("Synchronizing with 16-bit ANSI buffer\n");
     1710            textA = LOCAL_Lock(hInstance, es->hloc16);
     1711            countA = strlen(textA) + 1;
     1712            _16bit = TRUE;
     1713        }
     1714        }
     1715        else {
     1716        ERR("no buffer ... please report\n");
     1717        return;
     1718        }
     1719
     1720        if(textA)
     1721        {
     1722        HLOCAL hloc32W_new;
     1723        UINT countW_new = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
     1724        TRACE("%d bytes translated to %d WCHARs\n", countA, countW_new);
     1725        if(countW_new > es->buffer_size + 1)
     1726        {
     1727            UINT alloc_size = ROUND_TO_GROW(countW_new * sizeof(WCHAR));
     1728            TRACE("Resizing 32-bit UNICODE buffer from %d+1 to %d WCHARs\n", es->buffer_size, countW_new);
     1729            hloc32W_new = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
     1730            if(hloc32W_new)
     1731            {
     1732            es->hloc32W = hloc32W_new;
     1733            es->buffer_size = LocalSize(hloc32W_new)/sizeof(WCHAR) - 1;
     1734            TRACE("Real new size %d+1 WCHARs\n", es->buffer_size);
     1735            }
     1736            else
     1737            WARN("FAILED! Will synchronize partially\n");
     1738        }
     1739        }
     1740
     1741        /*TRACE("Locking 32-bit UNICODE buffer\n");*/
     1742        es->text = LocalLock(es->hloc32W);
     1743
     1744        if(textA)
     1745        {
     1746        MultiByteToWideChar(CP_ACP, 0, textA, countA, es->text, es->buffer_size + 1);
     1747        if(_16bit)
     1748            LOCAL_Unlock(hInstance, es->hloc16);
     1749        else
     1750            LocalUnlock(es->hloc32A);
     1751        }
     1752    }
     1753    es->lock_count++;
     1754}
     1755
     1756
     1757/*********************************************************************
     1758 *
     1759 *  EDIT_SL_InvalidateText
     1760 *
     1761 *  Called from EDIT_InvalidateText().
     1762 *  Does the job for single-line controls only.
    17301763 *
    17311764 */
    17321765static void EDIT_SL_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end)
    17331766{
    1734         RECT line_rect;
    1735         RECT rc;
    1736 
    1737         EDIT_GetLineRect(hwnd, es, 0, start, end, &line_rect);
    1738         if (IntersectRect(&rc, &line_rect, &es->format_rect))
    1739                 EDIT_UpdateText(hwnd, es, &rc, FALSE);
    1740 }
    1741 
    1742 
    1743 /*********************************************************************
    1744  *
    1745  *      EDIT_ML_InvalidateText
    1746  *
    1747  *      Called from EDIT_InvalidateText().
    1748  *      Does the job for multi-line controls only.
     1767    RECT line_rect;
     1768    RECT rc;
     1769
     1770    EDIT_GetLineRect(hwnd, es, 0, start, end, &line_rect);
     1771    if (IntersectRect(&rc, &line_rect, &es->format_rect))
     1772        EDIT_UpdateText(hwnd, es, &rc, FALSE);
     1773}
     1774
     1775
     1776/*********************************************************************
     1777 *
     1778 *  EDIT_ML_InvalidateText
     1779 *
     1780 *  Called from EDIT_InvalidateText().
     1781 *  Does the job for multi-line controls only.
    17491782 *
    17501783 */
    17511784static void EDIT_ML_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end)
    17521785{
    1753         INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    1754         INT sl = EDIT_EM_LineFromChar(es, start);
    1755         INT el = EDIT_EM_LineFromChar(es, end);
    1756         INT sc;
    1757         INT ec;
    1758         RECT rc1;
    1759         RECT rcWnd;
    1760         RECT rcLine;
    1761         RECT rcUpdate;
    1762         INT l;
    1763 
    1764         if ((el < es->y_offset) || (sl > es->y_offset + vlc))
    1765                 return;
    1766 
    1767         sc = start - EDIT_EM_LineIndex(es, sl);
    1768         ec = end - EDIT_EM_LineIndex(es, el);
    1769         if (sl < es->y_offset) {
    1770                 sl = es->y_offset;
    1771                 sc = 0;
    1772         }
    1773         if (el > es->y_offset + vlc) {
    1774                 el = es->y_offset + vlc;
    1775                 ec = EDIT_EM_LineLength(es, EDIT_EM_LineIndex(es, el));
    1776         }
    1777         GetClientRect(hwnd, &rc1);
    1778         IntersectRect(&rcWnd, &rc1, &es->format_rect);
    1779         if (sl == el) {
    1780                 EDIT_GetLineRect(hwnd, es, sl, sc, ec, &rcLine);
    1781                 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
    1782                         EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
    1783         } else {
    1784                 EDIT_GetLineRect(hwnd, es, sl, sc,
    1785                                 EDIT_EM_LineLength(es,
    1786                                         EDIT_EM_LineIndex(es, sl)),
    1787                                 &rcLine);
    1788                 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
    1789                         EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
    1790                 for (l = sl + 1 ; l < el ; l++) {
    1791                         EDIT_GetLineRect(hwnd, es, l, 0,
    1792                                 EDIT_EM_LineLength(es,
    1793                                         EDIT_EM_LineIndex(es, l)),
    1794                                 &rcLine);
    1795                         if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
    1796                                 EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
    1797                 }
    1798                 EDIT_GetLineRect(hwnd, es, el, 0, ec, &rcLine);
    1799                 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
    1800                         EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
    1801         }
    1802 }
    1803 
    1804 
    1805 /*********************************************************************
    1806  *
    1807  *      EDIT_InvalidateText
    1808  *
    1809  *      Invalidate the text from offset start upto, but not including,
    1810  *      offset end.  Useful for (re)painting the selection.
    1811  *      Regions outside the linewidth are not invalidated.
    1812  *      end == -1 means end == TextLength.
    1813  *      start and end need not be ordered.
     1786    INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     1787    INT sl = EDIT_EM_LineFromChar(es, start);
     1788    INT el = EDIT_EM_LineFromChar(es, end);
     1789    INT sc;
     1790    INT ec;
     1791    RECT rc1;
     1792    RECT rcWnd;
     1793    RECT rcLine;
     1794    RECT rcUpdate;
     1795    INT l;
     1796
     1797    if ((el < es->y_offset) || (sl > es->y_offset + vlc))
     1798        return;
     1799
     1800    sc = start - EDIT_EM_LineIndex(es, sl);
     1801    ec = end - EDIT_EM_LineIndex(es, el);
     1802    if (sl < es->y_offset) {
     1803        sl = es->y_offset;
     1804        sc = 0;
     1805    }
     1806    if (el > es->y_offset + vlc) {
     1807        el = es->y_offset + vlc;
     1808        ec = EDIT_EM_LineLength(es, EDIT_EM_LineIndex(es, el));
     1809    }
     1810    GetClientRect(hwnd, &rc1);
     1811    IntersectRect(&rcWnd, &rc1, &es->format_rect);
     1812    if (sl == el) {
     1813        EDIT_GetLineRect(hwnd, es, sl, sc, ec, &rcLine);
     1814        if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
     1815            EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
     1816    } else {
     1817        EDIT_GetLineRect(hwnd, es, sl, sc,
     1818                EDIT_EM_LineLength(es,
     1819                    EDIT_EM_LineIndex(es, sl)),
     1820                &rcLine);
     1821        if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
     1822            EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
     1823        for (l = sl + 1 ; l < el ; l++) {
     1824            EDIT_GetLineRect(hwnd, es, l, 0,
     1825                EDIT_EM_LineLength(es,
     1826                    EDIT_EM_LineIndex(es, l)),
     1827                &rcLine);
     1828            if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
     1829                EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
     1830        }
     1831        EDIT_GetLineRect(hwnd, es, el, 0, ec, &rcLine);
     1832        if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
     1833            EDIT_UpdateText(hwnd, es, &rcUpdate, FALSE);
     1834    }
     1835}
     1836
     1837
     1838/*********************************************************************
     1839 *
     1840 *  EDIT_InvalidateText
     1841 *
     1842 *  Invalidate the text from offset start upto, but not including,
     1843 *  offset end.  Useful for (re)painting the selection.
     1844 *  Regions outside the linewidth are not invalidated.
     1845 *  end == -1 means end == TextLength.
     1846 *  start and end need not be ordered.
    18141847 *
    18151848 */
    18161849static void EDIT_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end)
    18171850{
    1818         if (end == start)
    1819                 return;
    1820 
    1821         if (end == -1)
    1822                 end = strlenW(es->text);
    1823 
    1824         ORDER_INT(start, end);
    1825 
    1826         if (es->style & ES_MULTILINE)
    1827                 EDIT_ML_InvalidateText(hwnd, es, start, end);
    1828         else
    1829                 EDIT_SL_InvalidateText(hwnd, es, start, end);
    1830 }
    1831 
    1832 
    1833 /*********************************************************************
    1834  *
    1835  *      EDIT_MakeFit
    1836  *
    1837  *      Try to fit size + 1 characters in the buffer. Constrain to limits.
     1851    if (end == start)
     1852        return;
     1853
     1854    if (end == -1)
     1855        end = strlenW(es->text);
     1856
     1857    ORDER_INT(start, end);
     1858
     1859    if (es->style & ES_MULTILINE)
     1860        EDIT_ML_InvalidateText(hwnd, es, start, end);
     1861    else
     1862        EDIT_SL_InvalidateText(hwnd, es, start, end);
     1863}
     1864
     1865
     1866/*********************************************************************
     1867 *
     1868 *  EDIT_MakeFit
     1869 *
     1870 *  Try to fit size + 1 characters in the buffer. Constrain to limits.
    18381871 *
    18391872 */
    18401873static BOOL EDIT_MakeFit(HWND hwnd, EDITSTATE *es, UINT size)
    18411874{
    1842         HLOCAL hNew32W;
    1843 
    1844         if (size <= es->buffer_size)
    1845                 return TRUE;
     1875    HLOCAL hNew32W;
     1876
     1877    if (size <= es->buffer_size)
     1878        return TRUE;
    18461879#ifndef __WIN32OS2__
    1847 //SvL: EM_SETTEXTLIMIT has no effect in 
     1880//SvL: EM_SETTEXTLIMIT has no effect in
    18481881//     NT4, SP6 (EM_GETTEXTLIMIT only returns that value).
    18491882//     Limits are simply ignored, no EN_MAXTEXT notification is ever sent.
    18501883//     (fixes license edit control in Microsoft Visual C++ 4.2 install)
    18511884
    1852         if (size > es->buffer_limit) {
    1853                 EDIT_NOTIFY_PARENT(hwnd, es, EN_MAXTEXT, "EN_MAXTEXT");
    1854                 return FALSE;
    1855         }
    1856         if (size > es->buffer_limit)
    1857                 size = es->buffer_limit;
     1885    if (size > es->buffer_limit) {
     1886        EDIT_NOTIFY_PARENT(hwnd, es, EN_MAXTEXT, "EN_MAXTEXT");
     1887        return FALSE;
     1888    }
     1889    if (size > es->buffer_limit)
     1890        size = es->buffer_limit;
    18581891#endif
    18591892
    1860         TRACE("trying to ReAlloc to %d+1 characters\n", size);
    1861 
    1862         /* Force edit to unlock it's buffer. es->text now NULL */
    1863         EDIT_UnlockBuffer(hwnd, es, TRUE);
    1864 
    1865         if (es->hloc32W) {
    1866             UINT alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
    1867             if ((hNew32W = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT))) {
    1868                 TRACE("Old 32 bit handle %08x, new handle %08x\n", es->hloc32W, hNew32W);
    1869                 es->hloc32W = hNew32W;
    1870                 es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
    1871             }
    1872         }
    1873 
    1874         EDIT_LockBuffer(hwnd, es);
    1875 
    1876         if (es->buffer_size < size) {
    1877                 WARN("FAILED !  We now have %d+1\n", es->buffer_size);
    1878                 EDIT_NOTIFY_PARENT(hwnd, es, EN_ERRSPACE, "EN_ERRSPACE");
    1879                 return FALSE;
    1880         } else {
    1881                 TRACE("We now have %d+1\n", es->buffer_size);
    1882                 return TRUE;
    1883         }
    1884 }
    1885 
    1886 
    1887 /*********************************************************************
    1888  *
    1889  *      EDIT_MakeUndoFit
    1890  *
    1891  *      Try to fit size + 1 bytes in the undo buffer.
     1893    TRACE("trying to ReAlloc to %d+1 characters\n", size);
     1894
     1895    /* Force edit to unlock it's buffer. es->text now NULL */
     1896    EDIT_UnlockBuffer(hwnd, es, TRUE);
     1897
     1898    if (es->hloc32W) {
     1899        UINT alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
     1900        if ((hNew32W = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT))) {
     1901        TRACE("Old 32 bit handle %08x, new handle %08x\n", es->hloc32W, hNew32W);
     1902        es->hloc32W = hNew32W;
     1903        es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
     1904        }
     1905    }
     1906
     1907    EDIT_LockBuffer(hwnd, es);
     1908
     1909    if (es->buffer_size < size) {
     1910        WARN("FAILED !  We now have %d+1\n", es->buffer_size);
     1911        EDIT_NOTIFY_PARENT(hwnd, es, EN_ERRSPACE, "EN_ERRSPACE");
     1912        return FALSE;
     1913    } else {
     1914        TRACE("We now have %d+1\n", es->buffer_size);
     1915        return TRUE;
     1916    }
     1917}
     1918
     1919
     1920/*********************************************************************
     1921 *
     1922 *  EDIT_MakeUndoFit
     1923 *
     1924 *  Try to fit size + 1 bytes in the undo buffer.
    18921925 *
    18931926 */
    18941927static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size)
    18951928{
    1896         UINT alloc_size;
    1897 
    1898         if (size <= es->undo_buffer_size)
    1899                 return TRUE;
    1900 
    1901         TRACE("trying to ReAlloc to %d+1\n", size);
    1902 
    1903         alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
    1904         if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, alloc_size))) {
     1929    UINT alloc_size;
     1930
     1931    if (size <= es->undo_buffer_size)
     1932        return TRUE;
     1933
     1934    TRACE("trying to ReAlloc to %d+1\n", size);
     1935
     1936    alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
     1937    if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, alloc_size))) {
    19051938#ifdef __WIN32OS2__
    1906                 es->undo_buffer_size = alloc_size/sizeof(WCHAR) - 1;
     1939        es->undo_buffer_size = alloc_size/sizeof(WCHAR) - 1;
    19071940#else
    1908                 es->undo_buffer_size = alloc_size/sizeof(WCHAR);
     1941        es->undo_buffer_size = alloc_size/sizeof(WCHAR);
    19091942#endif
    1910                 return TRUE;
    1911         }
    1912         else
    1913         {
    1914                 WARN("FAILED !  We now have %d+1\n", es->undo_buffer_size);
    1915                 return FALSE;
    1916         }
    1917 }
    1918 
    1919 
    1920 /*********************************************************************
    1921  *
    1922  *      EDIT_MoveBackward
     1943        return TRUE;
     1944    }
     1945    else
     1946    {
     1947        WARN("FAILED !  We now have %d+1\n", es->undo_buffer_size);
     1948        return FALSE;
     1949    }
     1950}
     1951
     1952
     1953/*********************************************************************
     1954 *
     1955 *  EDIT_MoveBackward
    19231956 *
    19241957 */
    19251958static void EDIT_MoveBackward(HWND hwnd, EDITSTATE *es, BOOL extend)
    19261959{
    1927         INT e = es->selection_end;
    1928 
    1929         if (e) {
    1930                 e--;
    1931                 if ((es->style & ES_MULTILINE) && e &&
    1932                                 (es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
    1933                         e--;
    1934                         if (e && (es->text[e - 1] == '\r'))
    1935                                 e--;
    1936                 }
    1937         }
    1938         EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
    1939         EDIT_EM_ScrollCaret(hwnd, es);
    1940 }
    1941 
    1942 
    1943 /*********************************************************************
    1944  *
    1945  *      EDIT_MoveDown_ML
    1946  *
    1947  *      Only for multi line controls
    1948  *      Move the caret one line down, on a column with the nearest
    1949  *      x coordinate on the screen (might be a different column).
     1960    INT e = es->selection_end;
     1961
     1962    if (e) {
     1963        e--;
     1964        if ((es->style & ES_MULTILINE) && e &&
     1965                (es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
     1966            e--;
     1967            if (e && (es->text[e - 1] == '\r'))
     1968                e--;
     1969        }
     1970    }
     1971    EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
     1972    EDIT_EM_ScrollCaret(hwnd, es);
     1973}
     1974
     1975
     1976/*********************************************************************
     1977 *
     1978 *  EDIT_MoveDown_ML
     1979 *
     1980 *  Only for multi line controls
     1981 *  Move the caret one line down, on a column with the nearest
     1982 *  x coordinate on the screen (might be a different column).
    19501983 *
    19511984 */
    19521985static void EDIT_MoveDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
    19531986{
    1954         INT s = es->selection_start;
    1955         INT e = es->selection_end;
    1956         BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
    1957         LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
    1958         INT x = SLOWORD(pos);
    1959         INT y = SHIWORD(pos);
    1960 
    1961         e = EDIT_CharFromPos(hwnd, es, x, y + es->line_height, &after_wrap);
    1962         if (!extend)
    1963                 s = e;
    1964         EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
    1965         EDIT_EM_ScrollCaret(hwnd, es);
    1966 }
    1967 
    1968 
    1969 /*********************************************************************
    1970  *
    1971  *      EDIT_MoveEnd
     1987    INT s = es->selection_start;
     1988    INT e = es->selection_end;
     1989    BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
     1990    LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
     1991    INT x = SLOWORD(pos);
     1992    INT y = SHIWORD(pos);
     1993
     1994    e = EDIT_CharFromPos(hwnd, es, x, y + es->line_height, &after_wrap);
     1995    if (!extend)
     1996        s = e;
     1997    EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
     1998    EDIT_EM_ScrollCaret(hwnd, es);
     1999}
     2000
     2001
     2002/*********************************************************************
     2003 *
     2004 *  EDIT_MoveEnd
    19722005 *
    19732006 */
    19742007static void EDIT_MoveEnd(HWND hwnd, EDITSTATE *es, BOOL extend)
    19752008{
    1976         BOOL after_wrap = FALSE;
    1977         INT e;
    1978 
    1979         /* Pass a high value in x to make sure of receiving the end of the line */
    1980         if (es->style & ES_MULTILINE)
    1981                 e = EDIT_CharFromPos(hwnd, es, 0x3fffffff,
    1982                         HIWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
    1983         else
    1984                 e = strlenW(es->text);
    1985         EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, after_wrap);
    1986         EDIT_EM_ScrollCaret(hwnd, es);
    1987 }
    1988 
    1989 
    1990 /*********************************************************************
    1991  *
    1992  *      EDIT_MoveForward
     2009    BOOL after_wrap = FALSE;
     2010    INT e;
     2011
     2012    /* Pass a high value in x to make sure of receiving the end of the line */
     2013    if (es->style & ES_MULTILINE)
     2014        e = EDIT_CharFromPos(hwnd, es, 0x3fffffff,
     2015            HIWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
     2016    else
     2017        e = strlenW(es->text);
     2018    EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, after_wrap);
     2019    EDIT_EM_ScrollCaret(hwnd, es);
     2020}
     2021
     2022
     2023/*********************************************************************
     2024 *
     2025 *  EDIT_MoveForward
    19932026 *
    19942027 */
    19952028static void EDIT_MoveForward(HWND hwnd, EDITSTATE *es, BOOL extend)
    19962029{
    1997         INT e = es->selection_end;
    1998 
    1999         if (es->text[e]) {
    2000                 e++;
    2001                 if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
    2002                         if (es->text[e] == '\n')
    2003                                 e++;
    2004                         else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
    2005                                 e += 2;
    2006                 }
    2007         }
    2008         EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
    2009         EDIT_EM_ScrollCaret(hwnd, es);
    2010 }
    2011 
    2012 
    2013 /*********************************************************************
    2014  *
    2015  *      EDIT_MoveHome
    2016  *
    2017  *      Home key: move to beginning of line.
     2030    INT e = es->selection_end;
     2031
     2032    if (es->text[e]) {
     2033        e++;
     2034        if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
     2035            if (es->text[e] == '\n')
     2036                e++;
     2037            else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
     2038                e += 2;
     2039        }
     2040    }
     2041    EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
     2042    EDIT_EM_ScrollCaret(hwnd, es);
     2043}
     2044
     2045
     2046/*********************************************************************
     2047 *
     2048 *  EDIT_MoveHome
     2049 *
     2050 *  Home key: move to beginning of line.
    20182051 *
    20192052 */
    20202053static void EDIT_MoveHome(HWND hwnd, EDITSTATE *es, BOOL extend)
    20212054{
    2022         INT e;
    2023 
    2024         /* Pass the x_offset in x to make sure of receiving the first position of the line */
    2025         if (es->style & ES_MULTILINE)
    2026                 e = EDIT_CharFromPos(hwnd, es, -es->x_offset,
    2027                         HIWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
    2028         else
    2029                 e = 0;
    2030         EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
    2031         EDIT_EM_ScrollCaret(hwnd, es);
    2032 }
    2033 
    2034 
    2035 /*********************************************************************
    2036  *
    2037  *      EDIT_MovePageDown_ML
    2038  *
    2039  *      Only for multi line controls
    2040  *      Move the caret one page down, on a column with the nearest
    2041  *      x coordinate on the screen (might be a different column).
     2055    INT e;
     2056
     2057    /* Pass the x_offset in x to make sure of receiving the first position of the line */
     2058    if (es->style & ES_MULTILINE)
     2059        e = EDIT_CharFromPos(hwnd, es, -es->x_offset,
     2060            HIWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
     2061    else
     2062        e = 0;
     2063    EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
     2064    EDIT_EM_ScrollCaret(hwnd, es);
     2065}
     2066
     2067
     2068/*********************************************************************
     2069 *
     2070 *  EDIT_MovePageDown_ML
     2071 *
     2072 *  Only for multi line controls
     2073 *  Move the caret one page down, on a column with the nearest
     2074 *  x coordinate on the screen (might be a different column).
    20422075 *
    20432076 */
    20442077static void EDIT_MovePageDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
    20452078{
    2046         INT s = es->selection_start;
    2047         INT e = es->selection_end;
    2048         BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
    2049         LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
    2050         INT x = SLOWORD(pos);
    2051         INT y = SHIWORD(pos);
    2052 
    2053         e = EDIT_CharFromPos(hwnd, es, x,
    2054                 y + (es->format_rect.bottom - es->format_rect.top),
    2055                 &after_wrap);
    2056         if (!extend)
    2057                 s = e;
    2058         EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
    2059         EDIT_EM_ScrollCaret(hwnd, es);
    2060 }
    2061 
    2062 
    2063 /*********************************************************************
    2064  *
    2065  *      EDIT_MovePageUp_ML
    2066  *
    2067  *      Only for multi line controls
    2068  *      Move the caret one page up, on a column with the nearest
    2069  *      x coordinate on the screen (might be a different column).
     2079    INT s = es->selection_start;
     2080    INT e = es->selection_end;
     2081    BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
     2082    LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
     2083    INT x = SLOWORD(pos);
     2084    INT y = SHIWORD(pos);
     2085
     2086    e = EDIT_CharFromPos(hwnd, es, x,
     2087        y + (es->format_rect.bottom - es->format_rect.top),
     2088        &after_wrap);
     2089    if (!extend)
     2090        s = e;
     2091    EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
     2092    EDIT_EM_ScrollCaret(hwnd, es);
     2093}
     2094
     2095
     2096/*********************************************************************
     2097 *
     2098 *  EDIT_MovePageUp_ML
     2099 *
     2100 *  Only for multi line controls
     2101 *  Move the caret one page up, on a column with the nearest
     2102 *  x coordinate on the screen (might be a different column).
    20702103 *
    20712104 */
    20722105static void EDIT_MovePageUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
    20732106{
    2074         INT s = es->selection_start;
    2075         INT e = es->selection_end;
    2076         BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
    2077         LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
    2078         INT x = SLOWORD(pos);
    2079         INT y = SHIWORD(pos);
    2080 
    2081         e = EDIT_CharFromPos(hwnd, es, x,
    2082                 y - (es->format_rect.bottom - es->format_rect.top),
    2083                 &after_wrap);
    2084         if (!extend)
    2085                 s = e;
    2086         EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
    2087         EDIT_EM_ScrollCaret(hwnd, es);
    2088 }
    2089 
    2090 
    2091 /*********************************************************************
    2092  *
    2093  *      EDIT_MoveUp_ML
    2094  *
    2095  *      Only for multi line controls
    2096  *      Move the caret one line up, on a column with the nearest
    2097  *      x coordinate on the screen (might be a different column).
     2107    INT s = es->selection_start;
     2108    INT e = es->selection_end;
     2109    BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
     2110    LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
     2111    INT x = SLOWORD(pos);
     2112    INT y = SHIWORD(pos);
     2113
     2114    e = EDIT_CharFromPos(hwnd, es, x,
     2115        y - (es->format_rect.bottom - es->format_rect.top),
     2116        &after_wrap);
     2117    if (!extend)
     2118        s = e;
     2119    EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
     2120    EDIT_EM_ScrollCaret(hwnd, es);
     2121}
     2122
     2123
     2124/*********************************************************************
     2125 *
     2126 *  EDIT_MoveUp_ML
     2127 *
     2128 *  Only for multi line controls
     2129 *  Move the caret one line up, on a column with the nearest
     2130 *  x coordinate on the screen (might be a different column).
    20982131 *
    20992132 */
    21002133static void EDIT_MoveUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
    21012134{
    2102         INT s = es->selection_start;
    2103         INT e = es->selection_end;
    2104         BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
    2105         LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
    2106         INT x = SLOWORD(pos);
    2107         INT y = SHIWORD(pos);
    2108 
    2109         e = EDIT_CharFromPos(hwnd, es, x, y - es->line_height, &after_wrap);
    2110         if (!extend)
    2111                 s = e;
    2112         EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
    2113         EDIT_EM_ScrollCaret(hwnd, es);
    2114 }
    2115 
    2116 
    2117 /*********************************************************************
    2118  *
    2119  *      EDIT_MoveWordBackward
     2135    INT s = es->selection_start;
     2136    INT e = es->selection_end;
     2137    BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
     2138    LRESULT pos = EDIT_EM_PosFromChar(hwnd, es, e, after_wrap);
     2139    INT x = SLOWORD(pos);
     2140    INT y = SHIWORD(pos);
     2141
     2142    e = EDIT_CharFromPos(hwnd, es, x, y - es->line_height, &after_wrap);
     2143    if (!extend)
     2144        s = e;
     2145    EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
     2146    EDIT_EM_ScrollCaret(hwnd, es);
     2147}
     2148
     2149
     2150/*********************************************************************
     2151 *
     2152 *  EDIT_MoveWordBackward
    21202153 *
    21212154 */
    21222155static void EDIT_MoveWordBackward(HWND hwnd, EDITSTATE *es, BOOL extend)
    21232156{
    2124         INT s = es->selection_start;
    2125         INT e = es->selection_end;
    2126         INT l;
    2127         INT ll;
    2128         INT li;
    2129 
    2130         l = EDIT_EM_LineFromChar(es, e);
    2131         ll = EDIT_EM_LineLength(es, e);
    2132         li = EDIT_EM_LineIndex(es, l);
    2133         if (e - li == 0) {
    2134                 if (l) {
    2135                         li = EDIT_EM_LineIndex(es, l - 1);
    2136                         e = li + EDIT_EM_LineLength(es, li);
    2137                 }
    2138         } else {
    2139                 e = li + (INT)EDIT_CallWordBreakProc(es,
    2140                                 li, e - li, ll, WB_LEFT);
    2141         }
    2142         if (!extend)
    2143                 s = e;
    2144         EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
    2145         EDIT_EM_ScrollCaret(hwnd, es);
    2146 }
    2147 
    2148 
    2149 /*********************************************************************
    2150  *
    2151  *      EDIT_MoveWordForward
     2157    INT s = es->selection_start;
     2158    INT e = es->selection_end;
     2159    INT l;
     2160    INT ll;
     2161    INT li;
     2162
     2163    l = EDIT_EM_LineFromChar(es, e);
     2164    ll = EDIT_EM_LineLength(es, e);
     2165    li = EDIT_EM_LineIndex(es, l);
     2166    if (e - li == 0) {
     2167        if (l) {
     2168            li = EDIT_EM_LineIndex(es, l - 1);
     2169            e = li + EDIT_EM_LineLength(es, li);
     2170        }
     2171    } else {
     2172        e = li + (INT)EDIT_CallWordBreakProc(es,
     2173                li, e - li, ll, WB_LEFT);
     2174    }
     2175    if (!extend)
     2176        s = e;
     2177    EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
     2178    EDIT_EM_ScrollCaret(hwnd, es);
     2179}
     2180
     2181
     2182/*********************************************************************
     2183 *
     2184 *  EDIT_MoveWordForward
    21522185 *
    21532186 */
    21542187static void EDIT_MoveWordForward(HWND hwnd, EDITSTATE *es, BOOL extend)
    21552188{
    2156         INT s = es->selection_start;
    2157         INT e = es->selection_end;
    2158         INT l;
    2159         INT ll;
    2160         INT li;
    2161 
    2162         l = EDIT_EM_LineFromChar(es, e);
    2163         ll = EDIT_EM_LineLength(es, e);
    2164         li = EDIT_EM_LineIndex(es, l);
    2165         if (e - li == ll) {
    2166                 if ((es->style & ES_MULTILINE) && (l != es->line_count - 1))
    2167                         e = EDIT_EM_LineIndex(es, l + 1);
    2168         } else {
    2169                 e = li + EDIT_CallWordBreakProc(es,
    2170                                 li, e - li + 1, ll, WB_RIGHT);
    2171         }
    2172         if (!extend)
    2173                 s = e;
    2174         EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
    2175         EDIT_EM_ScrollCaret(hwnd, es);
    2176 }
    2177 
    2178 
    2179 /*********************************************************************
    2180  *
    2181  *      EDIT_PaintLine
     2189    INT s = es->selection_start;
     2190    INT e = es->selection_end;
     2191    INT l;
     2192    INT ll;
     2193    INT li;
     2194
     2195    l = EDIT_EM_LineFromChar(es, e);
     2196    ll = EDIT_EM_LineLength(es, e);
     2197    li = EDIT_EM_LineIndex(es, l);
     2198    if (e - li == ll) {
     2199        if ((es->style & ES_MULTILINE) && (l != es->line_count - 1))
     2200            e = EDIT_EM_LineIndex(es, l + 1);
     2201    } else {
     2202        e = li + EDIT_CallWordBreakProc(es,
     2203                li, e - li + 1, ll, WB_RIGHT);
     2204    }
     2205    if (!extend)
     2206        s = e;
     2207    EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
     2208    EDIT_EM_ScrollCaret(hwnd, es);
     2209}
     2210
     2211
     2212/*********************************************************************
     2213 *
     2214 *  EDIT_PaintLine
    21822215 *
    21832216 */
    21842217static void EDIT_PaintLine(HWND hwnd, EDITSTATE *es, HDC dc, INT line, BOOL rev)
    21852218{
    2186         INT s = es->selection_start;
    2187         INT e = es->selection_end;
    2188         INT li;
    2189         INT ll;
    2190         INT x;
    2191         INT y;
    2192         LRESULT pos;
    2193 
    2194         if (es->style & ES_MULTILINE) {
    2195                 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    2196                 if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count))
    2197                         return;
    2198         } else if (line)
    2199                 return;
    2200 
    2201         TRACE("line=%d\n", line);
    2202 
    2203         pos = EDIT_EM_PosFromChar(hwnd, es, EDIT_EM_LineIndex(es, line), FALSE);
    2204         x = SLOWORD(pos);
    2205         y = SHIWORD(pos);
    2206         li = EDIT_EM_LineIndex(es, line);
    2207         ll = EDIT_EM_LineLength(es, li);
    2208         s = es->selection_start;
    2209         e = es->selection_end;
    2210         ORDER_INT(s, e);
    2211         s = min(li + ll, max(li, s));
    2212         e = min(li + ll, max(li, e));
    2213         if (rev && (s != e) &&
    2214                         ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
    2215                 x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE);
    2216                 x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE);
    2217                 x += EDIT_PaintText(es, dc, x, y, line, e - li, li + ll - e, FALSE);
    2218         } else
    2219                 x += EDIT_PaintText(es, dc, x, y, line, 0, ll, FALSE);
    2220 }
    2221 
    2222 
    2223 /*********************************************************************
    2224  *
    2225  *      EDIT_PaintText
     2219    INT s = es->selection_start;
     2220    INT e = es->selection_end;
     2221    INT li;
     2222    INT ll;
     2223    INT x;
     2224    INT y;
     2225    LRESULT pos;
     2226
     2227    if (es->style & ES_MULTILINE) {
     2228        INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     2229        if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count))
     2230            return;
     2231    } else if (line)
     2232        return;
     2233
     2234    TRACE("line=%d\n", line);
     2235
     2236    pos = EDIT_EM_PosFromChar(hwnd, es, EDIT_EM_LineIndex(es, line), FALSE);
     2237    x = SLOWORD(pos);
     2238    y = SHIWORD(pos);
     2239    li = EDIT_EM_LineIndex(es, line);
     2240    ll = EDIT_EM_LineLength(es, li);
     2241    s = es->selection_start;
     2242    e = es->selection_end;
     2243    ORDER_INT(s, e);
     2244    s = min(li + ll, max(li, s));
     2245    e = min(li + ll, max(li, e));
     2246    if (rev && (s != e) &&
     2247            ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
     2248        x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE);
     2249        x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE);
     2250        x += EDIT_PaintText(es, dc, x, y, line, e - li, li + ll - e, FALSE);
     2251    } else
     2252        x += EDIT_PaintText(es, dc, x, y, line, 0, ll, FALSE);
     2253}
     2254
     2255
     2256/*********************************************************************
     2257 *
     2258 *  EDIT_PaintText
    22262259 *
    22272260 */
    22282261static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col, INT count, BOOL rev)
    22292262{
    2230         COLORREF BkColor;
    2231         COLORREF TextColor;
    2232         INT ret;
    2233         INT li;
    2234         INT BkMode;
    2235         SIZE size;
    2236 
    2237         if (!count)
    2238                 return 0;
    2239         BkMode = GetBkMode(dc);
    2240         BkColor = GetBkColor(dc);
    2241         TextColor = GetTextColor(dc);
    2242         if (rev) {
    2243                 SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
    2244                 SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
    2245                 SetBkMode( dc, OPAQUE);
    2246         }
    2247         li = EDIT_EM_LineIndex(es, line);
    2248         if (es->style & ES_MULTILINE) {
    2249                 ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
    2250                                         es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
    2251         } else {
    2252                 LPWSTR text = EDIT_GetPasswordPointer_SL(es);
    2253                 TextOutW(dc, x, y, text + li + col, count);
    2254                 GetTextExtentPoint32W(dc, text + li + col, count, &size);
    2255                 ret = size.cx;
    2256                 if (es->style & ES_PASSWORD)
    2257                         HeapFree(GetProcessHeap(), 0, text);
    2258         }
    2259         if (rev) {
    2260                 SetBkColor(dc, BkColor);
    2261                 SetTextColor(dc, TextColor);
    2262                 SetBkMode( dc, BkMode);
    2263         }
    2264         return ret;
    2265 }
    2266 
    2267 
    2268 /*********************************************************************
    2269  *
    2270  *      EDIT_SetCaretPos
     2263    COLORREF BkColor;
     2264    COLORREF TextColor;
     2265    INT ret;
     2266    INT li;
     2267    INT BkMode;
     2268    SIZE size;
     2269
     2270    if (!count)
     2271        return 0;
     2272    BkMode = GetBkMode(dc);
     2273    BkColor = GetBkColor(dc);
     2274    TextColor = GetTextColor(dc);
     2275    if (rev) {
     2276        SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
     2277        SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
     2278        SetBkMode( dc, OPAQUE);
     2279    }
     2280    li = EDIT_EM_LineIndex(es, line);
     2281    if (es->style & ES_MULTILINE) {
     2282        ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
     2283                    es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
     2284    } else {
     2285        LPWSTR text = EDIT_GetPasswordPointer_SL(es);
     2286        TextOutW(dc, x, y, text + li + col, count);
     2287        GetTextExtentPoint32W(dc, text + li + col, count, &size);
     2288        ret = size.cx;
     2289        if (es->style & ES_PASSWORD)
     2290            HeapFree(GetProcessHeap(), 0, text);
     2291    }
     2292    if (rev) {
     2293        SetBkColor(dc, BkColor);
     2294        SetTextColor(dc, TextColor);
     2295        SetBkMode( dc, BkMode);
     2296    }
     2297    return ret;
     2298}
     2299
     2300
     2301/*********************************************************************
     2302 *
     2303 *  EDIT_SetCaretPos
    22712304 *
    22722305 */
    22732306static void EDIT_SetCaretPos(HWND hwnd, EDITSTATE *es, INT pos,
    2274                              BOOL after_wrap)
    2275 {
    2276         LRESULT res = EDIT_EM_PosFromChar(hwnd, es, pos, after_wrap);
    2277         SetCaretPos(SLOWORD(res), SHIWORD(res));
    2278 }
    2279 
    2280 
    2281 /*********************************************************************
    2282  *
    2283  *      EDIT_SetRectNP
    2284  *
    2285  *      note:   this is not (exactly) the handler called on EM_SETRECTNP
    2286  *              it is also used to set the rect of a single line control
     2307                 BOOL after_wrap)
     2308{
     2309    LRESULT res = EDIT_EM_PosFromChar(hwnd, es, pos, after_wrap);
     2310    SetCaretPos(SLOWORD(res), SHIWORD(res));
     2311}
     2312
     2313
     2314/*********************************************************************
     2315 *
     2316 *  EDIT_SetRectNP
     2317 *
     2318 *  note:   this is not (exactly) the handler called on EM_SETRECTNP
     2319 *      it is also used to set the rect of a single line control
    22872320 *
    22882321 */
    22892322static void EDIT_SetRectNP(HWND hwnd, EDITSTATE *es, LPRECT rc)
    22902323{
    2291         CopyRect(&es->format_rect, rc);
    2292         if (es->style & WS_BORDER) {
    2293                 INT bw = GetSystemMetrics(SM_CXBORDER) + 1;
    2294                 if(TWEAK_WineLook == WIN31_LOOK)
    2295                         bw += 2;
    2296                 es->format_rect.left += bw;
    2297                 es->format_rect.top += bw;
    2298                 es->format_rect.right -= bw;
    2299                 es->format_rect.bottom -= bw;
    2300         }
    2301         es->format_rect.left += es->left_margin;
    2302         es->format_rect.right -= es->right_margin;
    2303         es->format_rect.right = max(es->format_rect.right, es->format_rect.left + es->char_width);
    2304         if (es->style & ES_MULTILINE)
    2305         {
    2306             INT fw, vlc, max_x_offset, max_y_offset;
    2307 
    2308             vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    2309             es->format_rect.bottom = es->format_rect.top + max(1, vlc) * es->line_height;
    2310 
    2311             /* correct es->x_offset */
    2312             fw = es->format_rect.right - es->format_rect.left;
    2313             max_x_offset = es->text_width - fw;
    2314             if(max_x_offset < 0) max_x_offset = 0;
    2315             if(es->x_offset > max_x_offset)
    2316                 es->x_offset = max_x_offset;
    2317 
    2318             /* correct es->y_offset */
    2319             max_y_offset = es->line_count - vlc;
    2320             if(max_y_offset < 0) max_y_offset = 0;
    2321             if(es->y_offset > max_y_offset)
    2322                 es->y_offset = max_y_offset;
    2323 
    2324             /* force scroll info update */
    2325             EDIT_UpdateScrollInfo(hwnd, es);
    2326         }
    2327         else
    2328         /* Windows doesn't care to fix text placement for SL controls */
    2329                 es->format_rect.bottom = es->format_rect.top + es->line_height;
    2330 
    2331         if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL))
    2332                 EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
    2333 }
    2334 
    2335 
    2336 /*********************************************************************
    2337  *
    2338  *      EDIT_UnlockBuffer
     2324    CopyRect(&es->format_rect, rc);
     2325    if (es->style & WS_BORDER) {
     2326        INT bw = GetSystemMetrics(SM_CXBORDER) + 1;
     2327        if(TWEAK_WineLook == WIN31_LOOK)
     2328            bw += 2;
     2329        es->format_rect.left += bw;
     2330        es->format_rect.top += bw;
     2331        es->format_rect.right -= bw;
     2332        es->format_rect.bottom -= bw;
     2333    }
     2334    es->format_rect.left += es->left_margin;
     2335    es->format_rect.right -= es->right_margin;
     2336    es->format_rect.right = max(es->format_rect.right, es->format_rect.left + es->char_width);
     2337    if (es->style & ES_MULTILINE)
     2338    {
     2339        INT fw, vlc, max_x_offset, max_y_offset;
     2340
     2341        vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     2342        es->format_rect.bottom = es->format_rect.top + max(1, vlc) * es->line_height;
     2343
     2344        /* correct es->x_offset */
     2345        fw = es->format_rect.right - es->format_rect.left;
     2346        max_x_offset = es->text_width - fw;
     2347        if(max_x_offset < 0) max_x_offset = 0;
     2348        if(es->x_offset > max_x_offset)
     2349        es->x_offset = max_x_offset;
     2350
     2351        /* correct es->y_offset */
     2352        max_y_offset = es->line_count - vlc;
     2353        if(max_y_offset < 0) max_y_offset = 0;
     2354        if(es->y_offset > max_y_offset)
     2355        es->y_offset = max_y_offset;
     2356
     2357        /* force scroll info update */
     2358        EDIT_UpdateScrollInfo(hwnd, es);
     2359    }
     2360    else
     2361    /* Windows doesn't care to fix text placement for SL controls */
     2362        es->format_rect.bottom = es->format_rect.top + es->line_height;
     2363
     2364    if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL))
     2365        EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
     2366}
     2367
     2368
     2369/*********************************************************************
     2370 *
     2371 *  EDIT_UnlockBuffer
    23392372 *
    23402373 */
     
    23462379    if(!IsWindow(hwnd))
    23472380    {
    2348         WARN("edit hwnd %04x already destroyed\n", hwnd);
    2349         return;
    2350     }
    2351 
    2352         if (!es) {
    2353                 ERR("no EDITSTATE ... please report\n");
    2354                 return;
    2355         }
    2356         if (!es->lock_count) {
    2357                 ERR("lock_count == 0 ... please report\n");
    2358                 return;
    2359         }
    2360         if (!es->text) {
    2361                 ERR("es->text == 0 ... please report\n");
    2362                 return;
    2363         }
    2364 
    2365         if (force || (es->lock_count == 1)) {
    2366             if (es->hloc32W) {
    2367                 CHAR *textA = NULL;
    2368                 BOOL _16bit = FALSE;
    2369                 UINT countA = 0;
    2370                 UINT countW = strlenW(es->text) + 1;
    2371 
    2372                 if(es->hloc32A)
    2373                 {
    2374                     UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL);
    2375                     TRACE("Synchronizing with 32-bit ANSI buffer\n");
    2376                     TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new);
    2377                     countA = LocalSize(es->hloc32A);
    2378                     if(countA_new > countA)
    2379                     {
    2380                         HLOCAL hloc32A_new;
    2381                         UINT alloc_size = ROUND_TO_GROW(countA_new);
    2382                         TRACE("Resizing 32-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size);
    2383                         hloc32A_new = LocalReAlloc(es->hloc32A, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
    2384                         if(hloc32A_new)
    2385                         {
    2386                             es->hloc32A = hloc32A_new;
    2387                             countA = LocalSize(hloc32A_new);
    2388                             TRACE("Real new size %d bytes\n", countA);
    2389                         }
    2390                         else
    2391                             WARN("FAILED! Will synchronize partially\n");
    2392                     }
    2393                     textA = LocalLock(es->hloc32A);
    2394                 }
    2395                 else if(es->hloc16)
    2396                 {
    2397                     UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL);
    2398                     TRACE("Synchronizing with 16-bit ANSI buffer\n");
    2399                     TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new);
    2400                     countA = LOCAL_Size(hInstance, es->hloc16);
    2401                     if(countA_new > countA)
    2402                     {
    2403                         HLOCAL16 hloc16_new;
    2404                         UINT alloc_size = ROUND_TO_GROW(countA_new);
    2405                         TRACE("Resizing 16-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size);
    2406                         hloc16_new = LOCAL_ReAlloc(hInstance, es->hloc16, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
    2407                         if(hloc16_new)
    2408                         {
    2409                             es->hloc16 = hloc16_new;
    2410                             countA = LOCAL_Size(hInstance, hloc16_new);
    2411                             TRACE("Real new size %d bytes\n", countA);
    2412                         }
    2413                         else
    2414                             WARN("FAILED! Will synchronize partially\n");
    2415                     }
    2416                     textA = LOCAL_Lock(hInstance, es->hloc16);
    2417                     _16bit = TRUE;
    2418                 }
    2419                 if(textA)
    2420                 {
    2421                     WideCharToMultiByte(CP_ACP, 0, es->text, countW, textA, countA, NULL, NULL);
    2422                     if(_16bit)
    2423                         LOCAL_Unlock(hInstance, es->hloc16);
    2424                     else
    2425                         LocalUnlock(es->hloc32A);
    2426                 }
    2427 
    2428                 LocalUnlock(es->hloc32W);
    2429                 es->text = NULL;
    2430             }
    2431             else {
    2432                 ERR("no buffer ... please report\n");
    2433                 return;
    2434             }
    2435         }
    2436         es->lock_count--;
    2437 }
    2438 
    2439 
    2440 /*********************************************************************
    2441  *
    2442  *      EDIT_UpdateScrollInfo
     2381    WARN("edit hwnd %04x already destroyed\n", hwnd);
     2382    return;
     2383    }
     2384
     2385    if (!es) {
     2386        ERR("no EDITSTATE ... please report\n");
     2387        return;
     2388    }
     2389    if (!es->lock_count) {
     2390        ERR("lock_count == 0 ... please report\n");
     2391        return;
     2392    }
     2393    if (!es->text) {
     2394        ERR("es->text == 0 ... please report\n");
     2395        return;
     2396    }
     2397
     2398    if (force || (es->lock_count == 1)) {
     2399        if (es->hloc32W) {
     2400        CHAR *textA = NULL;
     2401        BOOL _16bit = FALSE;
     2402        UINT countA = 0;
     2403        UINT countW = strlenW(es->text) + 1;
     2404
     2405        if(es->hloc32A)
     2406        {
     2407            UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL);
     2408            TRACE("Synchronizing with 32-bit ANSI buffer\n");
     2409            TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new);
     2410            countA = LocalSize(es->hloc32A);
     2411            if(countA_new > countA)
     2412            {
     2413            HLOCAL hloc32A_new;
     2414            UINT alloc_size = ROUND_TO_GROW(countA_new);
     2415            TRACE("Resizing 32-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size);
     2416            hloc32A_new = LocalReAlloc(es->hloc32A, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
     2417            if(hloc32A_new)
     2418            {
     2419                es->hloc32A = hloc32A_new;
     2420                countA = LocalSize(hloc32A_new);
     2421                TRACE("Real new size %d bytes\n", countA);
     2422            }
     2423            else
     2424                WARN("FAILED! Will synchronize partially\n");
     2425            }
     2426            textA = LocalLock(es->hloc32A);
     2427        }
     2428        else if(es->hloc16)
     2429        {
     2430            UINT countA_new = WideCharToMultiByte(CP_ACP, 0, es->text, countW, NULL, 0, NULL, NULL);
     2431            TRACE("Synchronizing with 16-bit ANSI buffer\n");
     2432            TRACE("%d WCHARs translated to %d bytes\n", countW, countA_new);
     2433            countA = LOCAL_Size(hInstance, es->hloc16);
     2434            if(countA_new > countA)
     2435            {
     2436            HLOCAL16 hloc16_new;
     2437            UINT alloc_size = ROUND_TO_GROW(countA_new);
     2438            TRACE("Resizing 16-bit ANSI buffer from %d to %d bytes\n", countA, alloc_size);
     2439            hloc16_new = LOCAL_ReAlloc(hInstance, es->hloc16, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
     2440            if(hloc16_new)
     2441            {
     2442                es->hloc16 = hloc16_new;
     2443                countA = LOCAL_Size(hInstance, hloc16_new);
     2444                TRACE("Real new size %d bytes\n", countA);
     2445            }
     2446            else
     2447                WARN("FAILED! Will synchronize partially\n");
     2448            }
     2449            textA = LOCAL_Lock(hInstance, es->hloc16);
     2450            _16bit = TRUE;
     2451        }
     2452        if(textA)
     2453        {
     2454            WideCharToMultiByte(CP_ACP, 0, es->text, countW, textA, countA, NULL, NULL);
     2455            if(_16bit)
     2456            LOCAL_Unlock(hInstance, es->hloc16);
     2457            else
     2458            LocalUnlock(es->hloc32A);
     2459        }
     2460
     2461        LocalUnlock(es->hloc32W);
     2462        es->text = NULL;
     2463        }
     2464        else {
     2465        ERR("no buffer ... please report\n");
     2466        return;
     2467        }
     2468    }
     2469    es->lock_count--;
     2470}
     2471
     2472
     2473/*********************************************************************
     2474 *
     2475 *  EDIT_UpdateScrollInfo
    24432476 *
    24442477 */
     
    24472480    if ((es->style & WS_VSCROLL) && !(es->flags & EF_VSCROLL_TRACK))
    24482481    {
    2449         SCROLLINFO si;
    2450         si.cbSize       = sizeof(SCROLLINFO);
    2451         si.fMask        = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
    2452         si.nMin         = 0;
    2453         si.nMax         = es->line_count - 1;
    2454         si.nPage        = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    2455         si.nPos         = es->y_offset;
    2456         TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
    2457                 si.nMin, si.nMax, si.nPage, si.nPos);
    2458         SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
     2482    SCROLLINFO si;
     2483    si.cbSize   = sizeof(SCROLLINFO);
     2484    si.fMask    = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
     2485    si.nMin     = 0;
     2486    si.nMax     = es->line_count - 1;
     2487    si.nPage    = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     2488    si.nPos     = es->y_offset;
     2489    TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
     2490        si.nMin, si.nMax, si.nPage, si.nPos);
     2491    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
    24592492    }
    24602493
    24612494    if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
    24622495    {
    2463         SCROLLINFO si;
    2464         si.cbSize       = sizeof(SCROLLINFO);
    2465         si.fMask        = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
    2466         si.nMin         = 0;
    2467         si.nMax         = es->text_width - 1;
    2468         si.nPage        = es->format_rect.right - es->format_rect.left;
    2469         si.nPos         = es->x_offset;
    2470         TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
    2471                 si.nMin, si.nMax, si.nPage, si.nPos);
    2472         SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
    2473     }
    2474 }
    2475 
    2476 /*********************************************************************
    2477  *
    2478  *      EDIT_WordBreakProc
    2479  *
    2480  *      Find the beginning of words.
    2481  *      Note:   unlike the specs for a WordBreakProc, this function only
    2482  *              allows to be called without linebreaks between s[0] upto
    2483  *              s[count - 1].  Remember it is only called
    2484  *              internally, so we can decide this for ourselves.
     2496    SCROLLINFO si;
     2497    si.cbSize   = sizeof(SCROLLINFO);
     2498    si.fMask    = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
     2499    si.nMin     = 0;
     2500    si.nMax     = es->text_width - 1;
     2501    si.nPage    = es->format_rect.right - es->format_rect.left;
     2502    si.nPos     = es->x_offset;
     2503    TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
     2504        si.nMin, si.nMax, si.nPage, si.nPos);
     2505    SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
     2506    }
     2507}
     2508
     2509/*********************************************************************
     2510 *
     2511 *  EDIT_WordBreakProc
     2512 *
     2513 *  Find the beginning of words.
     2514 *  Note:   unlike the specs for a WordBreakProc, this function only
     2515 *      allows to be called without linebreaks between s[0] upto
     2516 *      s[count - 1].  Remember it is only called
     2517 *      internally, so we can decide this for ourselves.
    24852518 *
    24862519 */
    24872520static INT CALLBACK EDIT_WordBreakProc(LPWSTR s, INT index, INT count, INT action)
    24882521{
    2489         INT ret = 0;
    2490 
    2491         TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
    2492 
    2493         if(!s) return 0;
    2494 
    2495         switch (action) {
    2496         case WB_LEFT:
    2497                 if (!count)
    2498                         break;
    2499                 if (index)
    2500                         index--;
    2501                 if (s[index] == ' ') {
    2502                         while (index && (s[index] == ' '))
    2503                                 index--;
    2504                         if (index) {
    2505                                 while (index && (s[index] != ' '))
    2506                                         index--;
    2507                                 if (s[index] == ' ')
    2508                                         index++;
    2509                         }
    2510                 } else {
    2511                         while (index && (s[index] != ' '))
    2512                                 index--;
    2513                         if (s[index] == ' ')
    2514                                 index++;
    2515                 }
    2516                 ret = index;
    2517                 break;
    2518         case WB_RIGHT:
    2519                 if (!count)
    2520                         break;
    2521                 if (index)
    2522                         index--;
    2523                 if (s[index] == ' ')
    2524                         while ((index < count) && (s[index] == ' ')) index++;
    2525                 else {
    2526                         while (s[index] && (s[index] != ' ') && (index < count))
    2527                                 index++;
    2528                         while ((s[index] == ' ') && (index < count)) index++;
    2529                 }
    2530                 ret = index;
    2531                 break;
    2532         case WB_ISDELIMITER:
    2533                 ret = (s[index] == ' ');
    2534                 break;
    2535         default:
    2536                 ERR("unknown action code, please report !\n");
    2537                 break;
    2538         }
    2539         return ret;
    2540 }
    2541 
    2542 
    2543 /*********************************************************************
    2544  *
    2545  *      EM_CHARFROMPOS
     2522    INT ret = 0;
     2523
     2524    TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
     2525
     2526    if(!s) return 0;
     2527
     2528    switch (action) {
     2529    case WB_LEFT:
     2530        if (!count)
     2531            break;
     2532        if (index)
     2533            index--;
     2534        if (s[index] == ' ') {
     2535            while (index && (s[index] == ' '))
     2536                index--;
     2537            if (index) {
     2538                while (index && (s[index] != ' '))
     2539                    index--;
     2540                if (s[index] == ' ')
     2541                    index++;
     2542            }
     2543        } else {
     2544            while (index && (s[index] != ' '))
     2545                index--;
     2546            if (s[index] == ' ')
     2547                index++;
     2548        }
     2549        ret = index;
     2550        break;
     2551    case WB_RIGHT:
     2552        if (!count)
     2553            break;
     2554        if (index)
     2555            index--;
     2556        if (s[index] == ' ')
     2557            while ((index < count) && (s[index] == ' ')) index++;
     2558        else {
     2559            while (s[index] && (s[index] != ' ') && (index < count))
     2560                index++;
     2561            while ((s[index] == ' ') && (index < count)) index++;
     2562        }
     2563        ret = index;
     2564        break;
     2565    case WB_ISDELIMITER:
     2566        ret = (s[index] == ' ');
     2567        break;
     2568    default:
     2569        ERR("unknown action code, please report !\n");
     2570        break;
     2571    }
     2572    return ret;
     2573}
     2574
     2575
     2576/*********************************************************************
     2577 *
     2578 *  EM_CHARFROMPOS
    25462579 *
    25472580 *      returns line number (not index) in high-order word of result.
    25482581 *      NB : Q137805 is unclear about this. POINT * pointer in lParam apply
    25492582 *      to Richedit, not to the edit control. Original documentation is valid.
    2550  *      FIXME: do the specs mean to return -1 if outside client area or
    2551  *              if outside formatting rectangle ???
     2583 *  FIXME: do the specs mean to return -1 if outside client area or
     2584 *      if outside formatting rectangle ???
    25522585 *
    25532586 */
    25542587static LRESULT EDIT_EM_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y)
    25552588{
    2556         POINT pt;
    2557         RECT rc;
    2558         INT index;
    2559 
    2560         pt.x = x;
    2561         pt.y = y;
    2562         GetClientRect(hwnd, &rc);
    2563         if (!PtInRect(&rc, pt))
    2564                 return -1;
    2565 
    2566         index = EDIT_CharFromPos(hwnd, es, x, y, NULL);
    2567         return MAKELONG(index, EDIT_EM_LineFromChar(es, index));
    2568 }
    2569 
    2570 
    2571 /*********************************************************************
    2572  *
    2573  *      EM_FMTLINES
     2589    POINT pt;
     2590    RECT rc;
     2591    INT index;
     2592
     2593    pt.x = x;
     2594    pt.y = y;
     2595    GetClientRect(hwnd, &rc);
     2596    if (!PtInRect(&rc, pt))
     2597        return -1;
     2598
     2599    index = EDIT_CharFromPos(hwnd, es, x, y, NULL);
     2600    return MAKELONG(index, EDIT_EM_LineFromChar(es, index));
     2601}
     2602
     2603
     2604/*********************************************************************
     2605 *
     2606 *  EM_FMTLINES
    25742607 *
    25752608 * Enable or disable soft breaks.
     
    25772610static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol)
    25782611{
    2579         es->flags &= ~EF_USE_SOFTBRK;
    2580         if (add_eol) {
    2581                 es->flags |= EF_USE_SOFTBRK;
    2582                 FIXME("soft break enabled, not implemented\n");
    2583         }
    2584         return add_eol;
    2585 }
    2586 
    2587 
    2588 /*********************************************************************
    2589  *
    2590  *      EM_GETHANDLE
    2591  *
    2592  *      Hopefully this won't fire back at us.
    2593  *      We always start with a fixed buffer in the local heap.
    2594  *      Despite of the documentation says that the local heap is used
    2595  *      only if DS_LOCALEDIT flag is set, NT and 2000 always allocate
    2596  *      buffer on the local heap.
     2612    es->flags &= ~EF_USE_SOFTBRK;
     2613    if (add_eol) {
     2614        es->flags |= EF_USE_SOFTBRK;
     2615        FIXME("soft break enabled, not implemented\n");
     2616    }
     2617    return add_eol;
     2618}
     2619
     2620
     2621/*********************************************************************
     2622 *
     2623 *  EM_GETHANDLE
     2624 *
     2625 *  Hopefully this won't fire back at us.
     2626 *  We always start with a fixed buffer in the local heap.
     2627 *  Despite of the documentation says that the local heap is used
     2628 *  only if DS_LOCALEDIT flag is set, NT and 2000 always allocate
     2629 *  buffer on the local heap.
    25972630 *
    25982631 */
    25992632static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es)
    26002633{
    2601         HLOCAL hLocal;
    2602 
    2603         if (!(es->style & ES_MULTILINE))
    2604                 return 0;
    2605 
    2606         if(es->is_unicode)
    2607             hLocal = es->hloc32W;
    2608         else
    2609         {
    2610             if(!es->hloc32A)
    2611             {
    2612                 CHAR *textA;
    2613                 UINT countA, alloc_size;
    2614                 TRACE("Allocating 32-bit ANSI alias buffer\n");
    2615                 countA = WideCharToMultiByte(CP_ACP, 0, es->text, -1, NULL, 0, NULL, NULL);
    2616                 alloc_size = ROUND_TO_GROW(countA);
    2617                 if(!(es->hloc32A = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
    2618                 {
    2619                     ERR("Could not allocate %d bytes for 32-bit ANSI alias buffer\n", alloc_size);
    2620                     return 0;
    2621                 }
    2622                 textA = LocalLock(es->hloc32A);
    2623                 WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, countA, NULL, NULL);
    2624                 LocalUnlock(es->hloc32A);
    2625             }
    2626             hLocal = es->hloc32A;
    2627         }
    2628 
    2629         TRACE("Returning %04X, LocalSize() = %d\n", hLocal, LocalSize(hLocal));
    2630         return hLocal;
     2634    HLOCAL hLocal;
     2635
     2636    if (!(es->style & ES_MULTILINE))
     2637        return 0;
     2638
     2639    if(es->is_unicode)
     2640        hLocal = es->hloc32W;
     2641    else
     2642    {
     2643        if(!es->hloc32A)
     2644        {
     2645        CHAR *textA;
     2646        UINT countA, alloc_size;
     2647        TRACE("Allocating 32-bit ANSI alias buffer\n");
     2648        countA = WideCharToMultiByte(CP_ACP, 0, es->text, -1, NULL, 0, NULL, NULL);
     2649        alloc_size = ROUND_TO_GROW(countA);
     2650        if(!(es->hloc32A = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
     2651        {
     2652            ERR("Could not allocate %d bytes for 32-bit ANSI alias buffer\n", alloc_size);
     2653            return 0;
     2654        }
     2655        textA = LocalLock(es->hloc32A);
     2656        WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, countA, NULL, NULL);
     2657        LocalUnlock(es->hloc32A);
     2658        }
     2659        hLocal = es->hloc32A;
     2660    }
     2661
     2662    TRACE("Returning %04X, LocalSize() = %d\n", hLocal, LocalSize(hLocal));
     2663    return hLocal;
    26312664}
    26322665
     
    26342667/*********************************************************************
    26352668 *
    2636  *      EM_GETHANDLE16
    2637  *
    2638  *      Hopefully this won't fire back at us.
    2639  *      We always start with a buffer in 32 bit linear memory.
    2640  *      However, with this message a 16 bit application requests
    2641  *      a handle of 16 bit local heap memory, where it expects to find
    2642  *      the text.
    2643  *      It's a pitty that from this moment on we have to use this
    2644  *      local heap, because applications may rely on the handle
    2645  *      in the future.
    2646  *
    2647  *      In this function we'll try to switch to local heap.
     2669 *  EM_GETHANDLE16
     2670 *
     2671 *  Hopefully this won't fire back at us.
     2672 *  We always start with a buffer in 32 bit linear memory.
     2673 *  However, with this message a 16 bit application requests
     2674 *  a handle of 16 bit local heap memory, where it expects to find
     2675 *  the text.
     2676 *  It's a pitty that from this moment on we have to use this
     2677 *  local heap, because applications may rely on the handle
     2678 *  in the future.
     2679 *
     2680 *  In this function we'll try to switch to local heap.
    26482681 */
    26492682static HLOCAL16 EDIT_EM_GetHandle16(HWND hwnd, EDITSTATE *es)
    26502683{
    26512684    HINSTANCE hInstance = GetWindowLongA( hwnd, GWL_HINSTANCE );
    2652         CHAR *textA;
    2653         UINT countA, alloc_size;
    2654 
    2655         if (!(es->style & ES_MULTILINE))
    2656                 return 0;
    2657 
    2658         if (es->hloc16)
    2659                 return es->hloc16;
    2660 
    2661         if (!LOCAL_HeapSize(hInstance)) {
    2662                 if (!LocalInit16(hInstance, 0,
    2663                                 GlobalSize16(hInstance))) {
    2664                         ERR("could not initialize local heap\n");
    2665                         return 0;
    2666                 }
    2667                 TRACE("local heap initialized\n");
    2668         }
    2669 
    2670         countA = WideCharToMultiByte(CP_ACP, 0, es->text, -1, NULL, 0, NULL, NULL);
    2671         alloc_size = ROUND_TO_GROW(countA);
    2672 
    2673         TRACE("Allocating 16-bit ANSI alias buffer\n");
    2674         if (!(es->hloc16 = LOCAL_Alloc(hInstance, LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size))) {
    2675                 ERR("could not allocate new 16 bit buffer\n");
    2676                 return 0;
    2677         }
    2678 
    2679         if (!(textA = (LPSTR)LOCAL_Lock(hInstance, es->hloc16))) {
    2680                 ERR("could not lock new 16 bit buffer\n");
    2681                 LOCAL_Free(hInstance, es->hloc16);
    2682                 es->hloc16 = 0;
    2683                 return 0;
    2684         }
    2685 
    2686         WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, countA, NULL, NULL);
    2687         LOCAL_Unlock(hInstance, es->hloc16);
    2688 
    2689         TRACE("Returning %04X, LocalSize() = %d\n", es->hloc16, LOCAL_Size(hInstance, es->hloc16));
    2690         return es->hloc16;
     2685    CHAR *textA;
     2686    UINT countA, alloc_size;
     2687
     2688    if (!(es->style & ES_MULTILINE))
     2689        return 0;
     2690
     2691    if (es->hloc16)
     2692        return es->hloc16;
     2693
     2694    if (!LOCAL_HeapSize(hInstance)) {
     2695        if (!LocalInit16(hInstance, 0,
     2696                GlobalSize16(hInstance))) {
     2697            ERR("could not initialize local heap\n");
     2698            return 0;
     2699        }
     2700        TRACE("local heap initialized\n");
     2701    }
     2702
     2703    countA = WideCharToMultiByte(CP_ACP, 0, es->text, -1, NULL, 0, NULL, NULL);
     2704    alloc_size = ROUND_TO_GROW(countA);
     2705
     2706    TRACE("Allocating 16-bit ANSI alias buffer\n");
     2707    if (!(es->hloc16 = LOCAL_Alloc(hInstance, LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size))) {
     2708        ERR("could not allocate new 16 bit buffer\n");
     2709        return 0;
     2710    }
     2711
     2712    if (!(textA = (LPSTR)LOCAL_Lock(hInstance, es->hloc16))) {
     2713        ERR("could not lock new 16 bit buffer\n");
     2714        LOCAL_Free(hInstance, es->hloc16);
     2715        es->hloc16 = 0;
     2716        return 0;
     2717    }
     2718
     2719    WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, countA, NULL, NULL);
     2720    LOCAL_Unlock(hInstance, es->hloc16);
     2721
     2722    TRACE("Returning %04X, LocalSize() = %d\n", es->hloc16, LOCAL_Size(hInstance, es->hloc16));
     2723    return es->hloc16;
    26912724}
    26922725#endif
     
    26942727/*********************************************************************
    26952728 *
    2696  *      EM_GETLINE
     2729 *  EM_GETLINE
    26972730 *
    26982731 */
    26992732static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPARAM lParam, BOOL unicode)
    27002733{
    2701         LPWSTR src;
    2702         INT line_len, dst_len;
    2703         INT i;
    2704 
    2705         if (es->style & ES_MULTILINE) {
    2706                 if (line >= es->line_count)
    2707                         return 0;
    2708         } else
    2709                 line = 0;
    2710         i = EDIT_EM_LineIndex(es, line);
    2711         src = es->text + i;
    2712         line_len = EDIT_EM_LineLength(es, i);
    2713         dst_len = *(WORD *)lParam;
    2714         if(unicode)
    2715         {
    2716             LPWSTR dst = (LPWSTR)lParam;
    2717             if(dst_len <= line_len)
    2718             {
    2719                 memcpy(dst, src, dst_len * sizeof(WCHAR));
    2720                 return dst_len;
    2721             }
    2722             else /* Append 0 if enough space */
    2723             {
    2724                 memcpy(dst, src, line_len * sizeof(WCHAR));
    2725                 dst[line_len] = 0;
    2726                 return line_len;
    2727             }
    2728         }
    2729         else
    2730         {
    2731             LPSTR dst = (LPSTR)lParam;
    2732             INT ret;
    2733             ret = WideCharToMultiByte(CP_ACP, 0, src, line_len, dst, dst_len, NULL, NULL);
    2734             if(!ret) /* Insufficient buffer size */
    2735                 return dst_len;
    2736             if(ret < dst_len) /* Append 0 if enough space */
    2737                 dst[ret] = 0;
    2738             return ret;
    2739         }
    2740 }
    2741 
    2742 
    2743 /*********************************************************************
    2744  *
    2745  *      EM_GETSEL
     2734    LPWSTR src;
     2735    INT line_len, dst_len;
     2736    INT i;
     2737
     2738    if (es->style & ES_MULTILINE) {
     2739        if (line >= es->line_count)
     2740            return 0;
     2741    } else
     2742        line = 0;
     2743    i = EDIT_EM_LineIndex(es, line);
     2744    src = es->text + i;
     2745    line_len = EDIT_EM_LineLength(es, i);
     2746    dst_len = *(WORD *)lParam;
     2747    if(unicode)
     2748    {
     2749        LPWSTR dst = (LPWSTR)lParam;
     2750        if(dst_len <= line_len)
     2751        {
     2752        memcpy(dst, src, dst_len * sizeof(WCHAR));
     2753        return dst_len;
     2754        }
     2755        else /* Append 0 if enough space */
     2756        {
     2757        memcpy(dst, src, line_len * sizeof(WCHAR));
     2758        dst[line_len] = 0;
     2759        return line_len;
     2760        }
     2761    }
     2762    else
     2763    {
     2764        LPSTR dst = (LPSTR)lParam;
     2765        INT ret;
     2766        ret = WideCharToMultiByte(CP_ACP, 0, src, line_len, dst, dst_len, NULL, NULL);
     2767        if(!ret) /* Insufficient buffer size */
     2768        return dst_len;
     2769        if(ret < dst_len) /* Append 0 if enough space */
     2770        dst[ret] = 0;
     2771        return ret;
     2772    }
     2773}
     2774
     2775
     2776/*********************************************************************
     2777 *
     2778 *  EM_GETSEL
    27462779 *
    27472780 */
    27482781static LRESULT EDIT_EM_GetSel(EDITSTATE *es, LPUINT start, LPUINT end)
    27492782{
    2750         UINT s = es->selection_start;
    2751         UINT e = es->selection_end;
    2752 
    2753         ORDER_UINT(s, e);
    2754         if (start)
    2755                 *start = s;
    2756         if (end)
    2757                 *end = e;
    2758         return MAKELONG(s, e);
    2759 }
    2760 
    2761 
    2762 /*********************************************************************
    2763  *
    2764  *      EM_GETTHUMB
    2765  *
    2766  *      FIXME: is this right ?  (or should it be only VSCROLL)
    2767  *      (and maybe only for edit controls that really have their
    2768  *      own scrollbars) (and maybe only for multiline controls ?)
    2769  *      All in all: very poorly documented
     2783    UINT s = es->selection_start;
     2784    UINT e = es->selection_end;
     2785
     2786    ORDER_UINT(s, e);
     2787    if (start)
     2788        *start = s;
     2789    if (end)
     2790        *end = e;
     2791    return MAKELONG(s, e);
     2792}
     2793
     2794
     2795/*********************************************************************
     2796 *
     2797 *  EM_GETTHUMB
     2798 *
     2799 *  FIXME: is this right ?  (or should it be only VSCROLL)
     2800 *  (and maybe only for edit controls that really have their
     2801 *  own scrollbars) (and maybe only for multiline controls ?)
     2802 *  All in all: very poorly documented
    27702803 *
    27712804 */
    27722805static LRESULT EDIT_EM_GetThumb(HWND hwnd, EDITSTATE *es)
    27732806{
    2774         return MAKELONG(EDIT_WM_VScroll(hwnd, es, EM_GETTHUMB16, 0),
    2775                 EDIT_WM_HScroll(hwnd, es, EM_GETTHUMB16, 0));
    2776 }
    2777 
    2778 
    2779 /*********************************************************************
    2780  *
    2781  *      EM_LINEFROMCHAR
     2807    return MAKELONG(EDIT_WM_VScroll(hwnd, es, EM_GETTHUMB16, 0),
     2808        EDIT_WM_HScroll(hwnd, es, EM_GETTHUMB16, 0));
     2809}
     2810
     2811
     2812/*********************************************************************
     2813 *
     2814 *  EM_LINEFROMCHAR
    27822815 *
    27832816 */
    27842817static INT EDIT_EM_LineFromChar(EDITSTATE *es, INT index)
    27852818{
    2786         INT line;
    2787         LINEDEF *line_def;
    2788 
    2789         if (!(es->style & ES_MULTILINE))
    2790                 return 0;
    2791         if (index > (INT)strlenW(es->text))
    2792                 return es->line_count - 1;
    2793         if (index == -1)
    2794                 index = min(es->selection_start, es->selection_end);
    2795 
    2796         line = 0;
    2797         line_def = es->first_line_def;
    2798         index -= line_def->length;
    2799         while ((index >= 0) && line_def->next) {
    2800                 line++;
    2801                 line_def = line_def->next;
    2802                 index -= line_def->length;
    2803         }
    2804         return line;
    2805 }
    2806 
    2807 
    2808 /*********************************************************************
    2809  *
    2810  *      EM_LINEINDEX
     2819    INT line;
     2820    LINEDEF *line_def;
     2821
     2822    if (!(es->style & ES_MULTILINE))
     2823        return 0;
     2824    if (index > (INT)strlenW(es->text))
     2825        return es->line_count - 1;
     2826    if (index == -1)
     2827        index = min(es->selection_start, es->selection_end);
     2828
     2829    line = 0;
     2830    line_def = es->first_line_def;
     2831    index -= line_def->length;
     2832    while ((index >= 0) && line_def->next) {
     2833        line++;
     2834        line_def = line_def->next;
     2835        index -= line_def->length;
     2836    }
     2837    return line;
     2838}
     2839
     2840
     2841/*********************************************************************
     2842 *
     2843 *  EM_LINEINDEX
    28112844 *
    28122845 */
    28132846static INT EDIT_EM_LineIndex(EDITSTATE *es, INT line)
    28142847{
    2815         INT line_index;
    2816         LINEDEF *line_def;
    2817 
    2818         if (!(es->style & ES_MULTILINE))
    2819                 return 0;
    2820         if (line >= es->line_count)
    2821                 return -1;
    2822 
    2823         line_index = 0;
    2824         line_def = es->first_line_def;
    2825         if (line == -1) {
    2826                 INT index = es->selection_end - line_def->length;
    2827                 while ((index >= 0) && line_def->next) {
    2828                         line_index += line_def->length;
    2829                         line_def = line_def->next;
    2830                         index -= line_def->length;
    2831                 }
    2832         } else {
    2833                 while (line > 0) {
    2834                         line_index += line_def->length;
    2835                         line_def = line_def->next;
    2836                         line--;
    2837                 }
    2838         }
    2839         return line_index;
    2840 }
    2841 
    2842 
    2843 /*********************************************************************
    2844  *
    2845  *      EM_LINELENGTH
     2848    INT line_index;
     2849    LINEDEF *line_def;
     2850
     2851    if (!(es->style & ES_MULTILINE))
     2852        return 0;
     2853    if (line >= es->line_count)
     2854        return -1;
     2855
     2856    line_index = 0;
     2857    line_def = es->first_line_def;
     2858    if (line == -1) {
     2859        INT index = es->selection_end - line_def->length;
     2860        while ((index >= 0) && line_def->next) {
     2861            line_index += line_def->length;
     2862            line_def = line_def->next;
     2863            index -= line_def->length;
     2864        }
     2865    } else {
     2866        while (line > 0) {
     2867            line_index += line_def->length;
     2868            line_def = line_def->next;
     2869            line--;
     2870        }
     2871    }
     2872    return line_index;
     2873}
     2874
     2875
     2876/*********************************************************************
     2877 *
     2878 *  EM_LINELENGTH
    28462879 *
    28472880 */
    28482881static INT EDIT_EM_LineLength(EDITSTATE *es, INT index)
    28492882{
    2850         LINEDEF *line_def;
    2851 
    2852         if (!(es->style & ES_MULTILINE))
    2853                 return strlenW(es->text);
    2854 
    2855         if (index == -1) {
    2856                 /* get the number of remaining non-selected chars of selected lines */
    2857                 INT32 l; /* line number */
    2858                 INT32 li; /* index of first char in line */
    2859                 INT32 count;
    2860                 l = EDIT_EM_LineFromChar(es, es->selection_start);
    2861                 /* # chars before start of selection area */
    2862                 count = es->selection_start - EDIT_EM_LineIndex(es, l);
    2863                 l = EDIT_EM_LineFromChar(es, es->selection_end);
    2864                 /* # chars after end of selection */
    2865                 li = EDIT_EM_LineIndex(es, l);
    2866                 count += li + EDIT_EM_LineLength(es, li) - es->selection_end;
    2867                 return count;
    2868         }
    2869         line_def = es->first_line_def;
    2870         index -= line_def->length;
    2871         while ((index >= 0) && line_def->next) {
    2872                 line_def = line_def->next;
    2873                 index -= line_def->length;
    2874         }
    2875         return line_def->net_length;
    2876 }
    2877 
    2878 
    2879 /*********************************************************************
    2880  *
    2881  *      EM_LINESCROLL
    2882  *
    2883  *      NOTE: dx is in average character widths, dy - in lines;
     2883    LINEDEF *line_def;
     2884
     2885    if (!(es->style & ES_MULTILINE))
     2886        return strlenW(es->text);
     2887
     2888    if (index == -1) {
     2889        /* get the number of remaining non-selected chars of selected lines */
     2890        INT32 l; /* line number */
     2891        INT32 li; /* index of first char in line */
     2892        INT32 count;
     2893        l = EDIT_EM_LineFromChar(es, es->selection_start);
     2894        /* # chars before start of selection area */
     2895        count = es->selection_start - EDIT_EM_LineIndex(es, l);
     2896        l = EDIT_EM_LineFromChar(es, es->selection_end);
     2897        /* # chars after end of selection */
     2898        li = EDIT_EM_LineIndex(es, l);
     2899        count += li + EDIT_EM_LineLength(es, li) - es->selection_end;
     2900        return count;
     2901    }
     2902    line_def = es->first_line_def;
     2903    index -= line_def->length;
     2904    while ((index >= 0) && line_def->next) {
     2905        line_def = line_def->next;
     2906        index -= line_def->length;
     2907    }
     2908    return line_def->net_length;
     2909}
     2910
     2911
     2912/*********************************************************************
     2913 *
     2914 *  EM_LINESCROLL
     2915 *
     2916 *  NOTE: dx is in average character widths, dy - in lines;
    28842917 *
    28852918 */
    28862919static BOOL EDIT_EM_LineScroll(HWND hwnd, EDITSTATE *es, INT dx, INT dy)
    28872920{
    2888         if (!(es->style & ES_MULTILINE))
    2889                 return FALSE;
    2890 
    2891         dx *= es->char_width;
    2892         return EDIT_EM_LineScroll_internal(hwnd, es, dx, dy);
    2893 }
    2894 
    2895 /*********************************************************************
    2896  *
    2897  *      EDIT_EM_LineScroll_internal
    2898  *
    2899  *      Version of EDIT_EM_LineScroll for internal use.
    2900  *      It doesn't refuse if ES_MULTILINE is set and assumes that
    2901  *      dx is in pixels, dy - in lines.
     2921    if (!(es->style & ES_MULTILINE))
     2922        return FALSE;
     2923
     2924    dx *= es->char_width;
     2925    return EDIT_EM_LineScroll_internal(hwnd, es, dx, dy);
     2926}
     2927
     2928/*********************************************************************
     2929 *
     2930 *  EDIT_EM_LineScroll_internal
     2931 *
     2932 *  Version of EDIT_EM_LineScroll for internal use.
     2933 *  It doesn't refuse if ES_MULTILINE is set and assumes that
     2934 *  dx is in pixels, dy - in lines.
    29022935 *
    29032936 */
    29042937static BOOL EDIT_EM_LineScroll_internal(HWND hwnd, EDITSTATE *es, INT dx, INT dy)
    29052938{
    2906         INT nyoff;
    2907         INT x_offset_in_pixels;
    2908 
    2909         if (es->style & ES_MULTILINE)
    2910         {
    2911             x_offset_in_pixels = es->x_offset;
    2912         }
    2913         else
    2914         {
    2915             dy = 0;
    2916             x_offset_in_pixels = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->x_offset, FALSE));
    2917         }
    2918 
    2919         if (-dx > x_offset_in_pixels)
    2920                 dx = -x_offset_in_pixels;
    2921         if (dx > es->text_width - x_offset_in_pixels)
    2922                 dx = es->text_width - x_offset_in_pixels;
    2923         nyoff = max(0, es->y_offset + dy);
    2924         if (nyoff >= es->line_count)
    2925                 nyoff = es->line_count - 1;
    2926         dy = (es->y_offset - nyoff) * es->line_height;
    2927         if (dx || dy) {
    2928                 RECT rc1;
    2929                 RECT rc;
    2930 
    2931                 es->y_offset = nyoff;
    2932                 if(es->style & ES_MULTILINE)
    2933                     es->x_offset += dx;
    2934                 else
    2935                     es->x_offset += dx / es->char_width;
    2936 
    2937                 GetClientRect(hwnd, &rc1);
    2938                 IntersectRect(&rc, &rc1, &es->format_rect);
    2939                 ScrollWindowEx(hwnd, -dx, dy,
    2940                                 NULL, &rc, (HRGN)NULL, NULL, SW_INVALIDATE);
    2941                 /* force scroll info update */
    2942                 EDIT_UpdateScrollInfo(hwnd, es);
    2943         }
    2944         if (dx && !(es->flags & EF_HSCROLL_TRACK))
    2945                 EDIT_NOTIFY_PARENT(hwnd, es, EN_HSCROLL, "EN_HSCROLL");
    2946         if (dy && !(es->flags & EF_VSCROLL_TRACK))
    2947                 EDIT_NOTIFY_PARENT(hwnd, es, EN_VSCROLL, "EN_VSCROLL");
    2948         return TRUE;
    2949 }
    2950 
    2951 
    2952 /*********************************************************************
    2953  *
    2954  *      EM_POSFROMCHAR
     2939    INT nyoff;
     2940    INT x_offset_in_pixels;
     2941
     2942    if (es->style & ES_MULTILINE)
     2943    {
     2944        x_offset_in_pixels = es->x_offset;
     2945    }
     2946    else
     2947    {
     2948        dy = 0;
     2949        x_offset_in_pixels = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->x_offset, FALSE));
     2950    }
     2951
     2952    if (-dx > x_offset_in_pixels)
     2953        dx = -x_offset_in_pixels;
     2954    if (dx > es->text_width - x_offset_in_pixels)
     2955        dx = es->text_width - x_offset_in_pixels;
     2956    nyoff = max(0, es->y_offset + dy);
     2957    if (nyoff >= es->line_count)
     2958        nyoff = es->line_count - 1;
     2959    dy = (es->y_offset - nyoff) * es->line_height;
     2960    if (dx || dy) {
     2961        RECT rc1;
     2962        RECT rc;
     2963
     2964        es->y_offset = nyoff;
     2965        if(es->style & ES_MULTILINE)
     2966            es->x_offset += dx;
     2967        else
     2968            es->x_offset += dx / es->char_width;
     2969
     2970        GetClientRect(hwnd, &rc1);
     2971        IntersectRect(&rc, &rc1, &es->format_rect);
     2972        ScrollWindowEx(hwnd, -dx, dy,
     2973                NULL, &rc, (HRGN)NULL, NULL, SW_INVALIDATE);
     2974        /* force scroll info update */
     2975        EDIT_UpdateScrollInfo(hwnd, es);
     2976    }
     2977    if (dx && !(es->flags & EF_HSCROLL_TRACK))
     2978        EDIT_NOTIFY_PARENT(hwnd, es, EN_HSCROLL, "EN_HSCROLL");
     2979    if (dy && !(es->flags & EF_VSCROLL_TRACK))
     2980        EDIT_NOTIFY_PARENT(hwnd, es, EN_VSCROLL, "EN_VSCROLL");
     2981    return TRUE;
     2982}
     2983
     2984
     2985/*********************************************************************
     2986 *
     2987 *  EM_POSFROMCHAR
    29552988 *
    29562989 */
    29572990static LRESULT EDIT_EM_PosFromChar(HWND hwnd, EDITSTATE *es, INT index, BOOL after_wrap)
    29582991{
    2959         INT len = strlenW(es->text);
    2960         INT l;
    2961         INT li;
    2962         INT x;
    2963         INT y = 0;
    2964         HDC dc;
    2965         HFONT old_font = 0;
    2966         SIZE size;
    2967 
    2968         index = min(index, len);
    2969         dc = GetDC(hwnd);
    2970         if (es->font)
    2971                 old_font = SelectObject(dc, es->font);
    2972         if (es->style & ES_MULTILINE) {
    2973                 l = EDIT_EM_LineFromChar(es, index);
    2974                 y = (l - es->y_offset) * es->line_height;
    2975                 li = EDIT_EM_LineIndex(es, l);
    2976                 if (after_wrap && (li == index) && l) {
    2977                         INT l2 = l - 1;
    2978                         LINEDEF *line_def = es->first_line_def;
    2979                         while (l2) {
    2980                                 line_def = line_def->next;
    2981                                 l2--;
    2982                         }
    2983                         if (line_def->ending == END_WRAP) {
    2984                                 l--;
    2985                                 y -= es->line_height;
    2986                                 li = EDIT_EM_LineIndex(es, l);
    2987                         }
    2988                 }
    2989                 x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
    2990                                 es->tabs_count, es->tabs)) - es->x_offset;
    2991         } else {
    2992                 LPWSTR text = EDIT_GetPasswordPointer_SL(es);
    2993                 if (index < es->x_offset) {
    2994                         GetTextExtentPoint32W(dc, text + index,
    2995                                         es->x_offset - index, &size);
    2996                         x = -size.cx;
    2997                 } else {
    2998                         GetTextExtentPoint32W(dc, text + es->x_offset,
    2999                                         index - es->x_offset, &size);
    3000                         x = size.cx;
    3001                 }
    3002                 y = 0;
    3003                 if (es->style & ES_PASSWORD)
    3004                         HeapFree(GetProcessHeap(), 0, text);
    3005         }
    3006         x += es->format_rect.left;
    3007         y += es->format_rect.top;
    3008         if (es->font)
    3009                 SelectObject(dc, old_font);
    3010         ReleaseDC(hwnd, dc);
    3011         return MAKELONG((INT16)x, (INT16)y);
    3012 }
    3013 
    3014 
    3015 /*********************************************************************
    3016  *
    3017  *      EM_REPLACESEL
    3018  *
    3019  *      FIXME: handle ES_NUMBER and ES_OEMCONVERT here
     2992    INT len = strlenW(es->text);
     2993    INT l;
     2994    INT li;
     2995    INT x;
     2996    INT y = 0;
     2997    HDC dc;
     2998    HFONT old_font = 0;
     2999    SIZE size;
     3000
     3001    index = min(index, len);
     3002    dc = GetDC(hwnd);
     3003    if (es->font)
     3004        old_font = SelectObject(dc, es->font);
     3005    if (es->style & ES_MULTILINE) {
     3006        l = EDIT_EM_LineFromChar(es, index);
     3007        y = (l - es->y_offset) * es->line_height;
     3008        li = EDIT_EM_LineIndex(es, l);
     3009        if (after_wrap && (li == index) && l) {
     3010            INT l2 = l - 1;
     3011            LINEDEF *line_def = es->first_line_def;
     3012            while (l2) {
     3013                line_def = line_def->next;
     3014                l2--;
     3015            }
     3016            if (line_def->ending == END_WRAP) {
     3017                l--;
     3018                y -= es->line_height;
     3019                li = EDIT_EM_LineIndex(es, l);
     3020            }
     3021        }
     3022        x = LOWORD(GetTabbedTextExtentW(dc, es->text + li, index - li,
     3023                es->tabs_count, es->tabs)) - es->x_offset;
     3024    } else {
     3025        LPWSTR text = EDIT_GetPasswordPointer_SL(es);
     3026        if (index < es->x_offset) {
     3027            GetTextExtentPoint32W(dc, text + index,
     3028                    es->x_offset - index, &size);
     3029            x = -size.cx;
     3030        } else {
     3031            GetTextExtentPoint32W(dc, text + es->x_offset,
     3032                    index - es->x_offset, &size);
     3033            x = size.cx;
     3034        }
     3035        y = 0;
     3036        if (es->style & ES_PASSWORD)
     3037            HeapFree(GetProcessHeap(), 0, text);
     3038    }
     3039    x += es->format_rect.left;
     3040    y += es->format_rect.top;
     3041    if (es->font)
     3042        SelectObject(dc, old_font);
     3043    ReleaseDC(hwnd, dc);
     3044    return MAKELONG((INT16)x, (INT16)y);
     3045}
     3046
     3047
     3048/*********************************************************************
     3049 *
     3050 *  EM_REPLACESEL
     3051 *
     3052 *  FIXME: handle ES_NUMBER and ES_OEMCONVERT here
    30203053 *
    30213054 */
    30223055static void EDIT_EM_ReplaceSel(HWND hwnd, EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update)
    30233056{
    3024         UINT strl = strlenW(lpsz_replace);
    3025         UINT tl = strlenW(es->text);
    3026         UINT utl;
    3027         UINT s;
    3028         UINT e;
    3029         UINT i;
    3030         LPWSTR p;
    3031         HRGN hrgn = 0;
    3032 
    3033         TRACE("%s, can_undo %d, send_update %d\n",
    3034             debugstr_w(lpsz_replace), can_undo, send_update);
    3035 
    3036         s = es->selection_start;
    3037         e = es->selection_end;
    3038 
    3039         if ((s == e) && !strl)
    3040                 return;
    3041 
    3042         ORDER_UINT(s, e);
    3043 
    3044         if (!EDIT_MakeFit(hwnd, es, tl - (e - s) + strl))
    3045                 return;
    3046 
    3047         if (e != s) {
    3048                 /* there is something to be deleted */
    3049                 TRACE("deleting stuff.\n");
    3050                 if (can_undo) {
    3051                         utl = strlenW(es->undo_text);
    3052                         if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
    3053                                 /* undo-buffer is extended to the right */
    3054                                 EDIT_MakeUndoFit(es, utl + e - s);
    3055                                 strncpyW(es->undo_text + utl, es->text + s, e - s + 1);
    3056                                 (es->undo_text + utl)[e - s] = 0; /* ensure 0 termination */
    3057                         } else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
    3058                                 /* undo-buffer is extended to the left */
    3059                                 EDIT_MakeUndoFit(es, utl + e - s);
    3060                                 for (p = es->undo_text + utl ; p >= es->undo_text ; p--)
    3061                                         p[e - s] = p[0];
    3062                                 for (i = 0 , p = es->undo_text ; i < e - s ; i++)
    3063                                         p[i] = (es->text + s)[i];
    3064                                 es->undo_position = s;
    3065                         } else {
    3066                                 /* new undo-buffer */
    3067                                 EDIT_MakeUndoFit(es, e - s);
    3068                                 strncpyW(es->undo_text, es->text + s, e - s + 1);
    3069                                 es->undo_text[e - s] = 0; /* ensure 0 termination */
    3070                                 es->undo_position = s;
    3071                         }
    3072                         /* any deletion makes the old insertion-undo invalid */
    3073                         es->undo_insert_count = 0;
    3074                 } else
    3075                         EDIT_EM_EmptyUndoBuffer(es);
    3076 
    3077                 /* now delete */
    3078                 strcpyW(es->text + s, es->text + e);
    3079         }
    3080         if (strl) {
    3081                 /* there is an insertion */
    3082                 if (can_undo) {
    3083                         if ((s == es->undo_position) ||
    3084                                         ((es->undo_insert_count) &&
    3085                                         (s == es->undo_position + es->undo_insert_count)))
    3086                                 /*
    3087                                 * insertion is new and at delete position or
    3088                                 * an extension to either left or right
    3089                                 */
    3090                                 es->undo_insert_count += strl;
    3091                         else {
    3092                                 /* new insertion undo */
    3093                                 es->undo_position = s;
    3094                                 es->undo_insert_count = strl;
    3095                                 /* new insertion makes old delete-buffer invalid */
    3096                                 *es->undo_text = '\0';
    3097                         }
    3098                 } else
    3099                         EDIT_EM_EmptyUndoBuffer(es);
    3100 
    3101                 /* now insert */
    3102                 tl = strlenW(es->text);
    3103                 TRACE("inserting stuff (tl %d, strl %d, selstart %d ('%s'), text '%s')\n", tl, strl, s, debugstr_w(es->text + s), debugstr_w(es->text));
    3104                 for (p = es->text + tl ; p >= es->text + s ; p--)
    3105                         p[strl] = p[0];
    3106                 for (i = 0 , p = es->text + s ; i < strl ; i++)
    3107                         p[i] = lpsz_replace[i];
    3108                 if(es->style & ES_UPPERCASE)
    3109                         CharUpperBuffW(p, strl);
    3110                 else if(es->style & ES_LOWERCASE)
    3111                         CharLowerBuffW(p, strl);
    3112                 s += strl;
    3113         }
    3114         if (es->style & ES_MULTILINE)
    3115         {
    3116                 INT s = min(es->selection_start, es->selection_end);
    3117 
    3118                 hrgn = CreateRectRgn(0, 0, 0, 0);
    3119                 EDIT_BuildLineDefs_ML(hwnd, es, s, s + strl,
    3120                                 strl - abs(es->selection_end - es->selection_start), hrgn);
    3121         }
    3122         else
    3123             EDIT_CalcLineWidth_SL(hwnd, es);
    3124 
    3125         EDIT_EM_SetSel(hwnd, es, s, s, FALSE);
    3126         es->flags |= EF_MODIFIED;
    3127         if (send_update) es->flags |= EF_UPDATE;
    3128         EDIT_EM_ScrollCaret(hwnd, es);
    3129 
    3130         /* force scroll info update */
    3131         EDIT_UpdateScrollInfo(hwnd, es);
    3132 
    3133         if (hrgn)
    3134         {
    3135                 EDIT_UpdateTextRegion(hwnd, es, hrgn, TRUE);
    3136                 DeleteObject(hrgn);
    3137         }
    3138         else
    3139         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3140 
    3141         if(es->flags & EF_UPDATE)
    3142         {
    3143             es->flags &= ~EF_UPDATE;
    3144             EDIT_NOTIFY_PARENT(hwnd, es, EN_CHANGE, "EN_CHANGE");
    3145         }
    3146 }
    3147 
    3148 
    3149 /*********************************************************************
    3150  *
    3151  *      EM_SCROLL
     3057    UINT strl = strlenW(lpsz_replace);
     3058    UINT tl = strlenW(es->text);
     3059    UINT utl;
     3060    UINT s;
     3061    UINT e;
     3062    UINT i;
     3063    LPWSTR p;
     3064    HRGN hrgn = 0;
     3065
     3066    TRACE("%s, can_undo %d, send_update %d\n",
     3067        debugstr_w(lpsz_replace), can_undo, send_update);
     3068
     3069    s = es->selection_start;
     3070    e = es->selection_end;
     3071
     3072    if ((s == e) && !strl)
     3073        return;
     3074
     3075    ORDER_UINT(s, e);
     3076
     3077    if (!EDIT_MakeFit(hwnd, es, tl - (e - s) + strl))
     3078        return;
     3079
     3080    if (e != s) {
     3081        /* there is something to be deleted */
     3082        TRACE("deleting stuff.\n");
     3083        if (can_undo) {
     3084            utl = strlenW(es->undo_text);
     3085            if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
     3086                /* undo-buffer is extended to the right */
     3087                EDIT_MakeUndoFit(es, utl + e - s);
     3088                strncpyW(es->undo_text + utl, es->text + s, e - s + 1);
     3089                (es->undo_text + utl)[e - s] = 0; /* ensure 0 termination */
     3090            } else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
     3091                /* undo-buffer is extended to the left */
     3092                EDIT_MakeUndoFit(es, utl + e - s);
     3093                for (p = es->undo_text + utl ; p >= es->undo_text ; p--)
     3094                    p[e - s] = p[0];
     3095                for (i = 0 , p = es->undo_text ; i < e - s ; i++)
     3096                    p[i] = (es->text + s)[i];
     3097                es->undo_position = s;
     3098            } else {
     3099                /* new undo-buffer */
     3100                EDIT_MakeUndoFit(es, e - s);
     3101                strncpyW(es->undo_text, es->text + s, e - s + 1);
     3102                es->undo_text[e - s] = 0; /* ensure 0 termination */
     3103                es->undo_position = s;
     3104            }
     3105            /* any deletion makes the old insertion-undo invalid */
     3106            es->undo_insert_count = 0;
     3107        } else
     3108            EDIT_EM_EmptyUndoBuffer(es);
     3109
     3110        /* now delete */
     3111        strcpyW(es->text + s, es->text + e);
     3112    }
     3113    if (strl) {
     3114        /* there is an insertion */
     3115        if (can_undo) {
     3116            if ((s == es->undo_position) ||
     3117                    ((es->undo_insert_count) &&
     3118                    (s == es->undo_position + es->undo_insert_count)))
     3119                /*
     3120                * insertion is new and at delete position or
     3121                * an extension to either left or right
     3122                */
     3123                es->undo_insert_count += strl;
     3124            else {
     3125                /* new insertion undo */
     3126                es->undo_position = s;
     3127                es->undo_insert_count = strl;
     3128                /* new insertion makes old delete-buffer invalid */
     3129                *es->undo_text = '\0';
     3130            }
     3131        } else
     3132            EDIT_EM_EmptyUndoBuffer(es);
     3133
     3134        /* now insert */
     3135        tl = strlenW(es->text);
     3136        TRACE("inserting stuff (tl %d, strl %d, selstart %d ('%s'), text '%s')\n", tl, strl, s, debugstr_w(es->text + s), debugstr_w(es->text));
     3137        for (p = es->text + tl ; p >= es->text + s ; p--)
     3138            p[strl] = p[0];
     3139        for (i = 0 , p = es->text + s ; i < strl ; i++)
     3140            p[i] = lpsz_replace[i];
     3141        if(es->style & ES_UPPERCASE)
     3142            CharUpperBuffW(p, strl);
     3143        else if(es->style & ES_LOWERCASE)
     3144            CharLowerBuffW(p, strl);
     3145        s += strl;
     3146    }
     3147    if (es->style & ES_MULTILINE)
     3148    {
     3149        INT s = min(es->selection_start, es->selection_end);
     3150
     3151        hrgn = CreateRectRgn(0, 0, 0, 0);
     3152        EDIT_BuildLineDefs_ML(hwnd, es, s, s + strl,
     3153                strl - abs(es->selection_end - es->selection_start), hrgn);
     3154    }
     3155    else
     3156        EDIT_CalcLineWidth_SL(hwnd, es);
     3157
     3158    EDIT_EM_SetSel(hwnd, es, s, s, FALSE);
     3159    es->flags |= EF_MODIFIED;
     3160    if (send_update) es->flags |= EF_UPDATE;
     3161    EDIT_EM_ScrollCaret(hwnd, es);
     3162
     3163    /* force scroll info update */
     3164    EDIT_UpdateScrollInfo(hwnd, es);
     3165
     3166    if (hrgn)
     3167    {
     3168        EDIT_UpdateTextRegion(hwnd, es, hrgn, TRUE);
     3169        DeleteObject(hrgn);
     3170    }
     3171    else
     3172    EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3173
     3174    if(es->flags & EF_UPDATE)
     3175    {
     3176        es->flags &= ~EF_UPDATE;
     3177        EDIT_NOTIFY_PARENT(hwnd, es, EN_CHANGE, "EN_CHANGE");
     3178    }
     3179}
     3180
     3181
     3182/*********************************************************************
     3183 *
     3184 *  EM_SCROLL
    31523185 *
    31533186 */
    31543187static LRESULT EDIT_EM_Scroll(HWND hwnd, EDITSTATE *es, INT action)
    31553188{
    3156         INT dy;
    3157 
    3158         if (!(es->style & ES_MULTILINE))
    3159                 return (LRESULT)FALSE;
    3160 
    3161         dy = 0;
    3162 
    3163         switch (action) {
    3164         case SB_LINEUP:
    3165                 if (es->y_offset)
    3166                         dy = -1;
    3167                 break;
    3168         case SB_LINEDOWN:
    3169                 if (es->y_offset < es->line_count - 1)
    3170                         dy = 1;
    3171                 break;
    3172         case SB_PAGEUP:
    3173                 if (es->y_offset)
    3174                         dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
    3175                 break;
    3176         case SB_PAGEDOWN:
    3177                 if (es->y_offset < es->line_count - 1)
    3178                         dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    3179                 break;
    3180         default:
    3181                 return (LRESULT)FALSE;
    3182         }
    3183         if (dy) {
    3184             INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    3185             /* check if we are going to move too far */
    3186             if(es->y_offset + dy > es->line_count - vlc)
    3187                 dy = es->line_count - vlc - es->y_offset;
    3188 
    3189             /* Notification is done in EDIT_EM_LineScroll */
    3190             if(dy)
    3191                 EDIT_EM_LineScroll(hwnd, es, 0, dy);
    3192         }
    3193         return MAKELONG((INT16)dy, (BOOL16)TRUE);
    3194 }
    3195 
    3196 
    3197 /*********************************************************************
    3198  *
    3199  *      EM_SCROLLCARET
     3189    INT dy;
     3190
     3191    if (!(es->style & ES_MULTILINE))
     3192        return (LRESULT)FALSE;
     3193
     3194    dy = 0;
     3195
     3196    switch (action) {
     3197    case SB_LINEUP:
     3198        if (es->y_offset)
     3199            dy = -1;
     3200        break;
     3201    case SB_LINEDOWN:
     3202        if (es->y_offset < es->line_count - 1)
     3203            dy = 1;
     3204        break;
     3205    case SB_PAGEUP:
     3206        if (es->y_offset)
     3207            dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
     3208        break;
     3209    case SB_PAGEDOWN:
     3210        if (es->y_offset < es->line_count - 1)
     3211            dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     3212        break;
     3213    default:
     3214        return (LRESULT)FALSE;
     3215    }
     3216    if (dy) {
     3217        INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     3218        /* check if we are going to move too far */
     3219        if(es->y_offset + dy > es->line_count - vlc)
     3220        dy = es->line_count - vlc - es->y_offset;
     3221
     3222        /* Notification is done in EDIT_EM_LineScroll */
     3223        if(dy)
     3224        EDIT_EM_LineScroll(hwnd, es, 0, dy);
     3225    }
     3226    return MAKELONG((INT16)dy, (BOOL16)TRUE);
     3227}
     3228
     3229
     3230/*********************************************************************
     3231 *
     3232 *  EM_SCROLLCARET
    32003233 *
    32013234 */
    32023235static void EDIT_EM_ScrollCaret(HWND hwnd, EDITSTATE *es)
    32033236{
    3204         if (es->style & ES_MULTILINE) {
    3205                 INT l;
    3206                 INT li;
    3207                 INT vlc;
    3208                 INT ww;
    3209                 INT cw = es->char_width;
    3210                 INT x;
    3211                 INT dy = 0;
    3212                 INT dx = 0;
    3213 
    3214                 l = EDIT_EM_LineFromChar(es, es->selection_end);
    3215                 li = EDIT_EM_LineIndex(es, l);
    3216                 x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP));
    3217                 vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    3218                 if (l >= es->y_offset + vlc)
    3219                         dy = l - vlc + 1 - es->y_offset;
    3220                 if (l < es->y_offset)
    3221                         dy = l - es->y_offset;
    3222                 ww = es->format_rect.right - es->format_rect.left;
    3223                 if (x < es->format_rect.left)
    3224                         dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
    3225                 if (x > es->format_rect.right)
    3226                         dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
    3227                 if (dy || dx)
    3228                 {
    3229                     /* check if we are going to move too far */
    3230                     if(es->x_offset + dx + ww > es->text_width)
    3231                         dx = es->text_width - ww - es->x_offset;
    3232                     if(dx || dy)
    3233                         EDIT_EM_LineScroll_internal(hwnd, es, dx, dy);
    3234                 }
    3235         } else {
    3236                 INT x;
    3237                 INT goal;
    3238                 INT format_width;
    3239 
    3240                 if (!(es->style & ES_AUTOHSCROLL))
    3241                         return;
    3242 
    3243                 x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, FALSE));
    3244                 format_width = es->format_rect.right - es->format_rect.left;
    3245                 if (x < es->format_rect.left) {
    3246                         goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
    3247                         do {
    3248                                 es->x_offset--;
    3249                                 x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, FALSE));
    3250                         } while ((x < goal) && es->x_offset);
    3251                         /* FIXME: use ScrollWindow() somehow to improve performance */
    3252                         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3253                 } else if (x > es->format_rect.right) {
    3254                         INT x_last;
    3255                         INT len = strlenW(es->text);
    3256                         goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
    3257                         do {
    3258                                 es->x_offset++;
    3259                                 x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, FALSE));
    3260                                 x_last = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, len, FALSE));
    3261                         } while ((x > goal) && (x_last > es->format_rect.right));
    3262                         /* FIXME: use ScrollWindow() somehow to improve performance */
    3263                         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3264                 }
    3265         }
     3237    if (es->style & ES_MULTILINE) {
     3238        INT l;
     3239        INT li;
     3240        INT vlc;
     3241        INT ww;
     3242        INT cw = es->char_width;
     3243        INT x;
     3244        INT dy = 0;
     3245        INT dx = 0;
     3246
     3247        l = EDIT_EM_LineFromChar(es, es->selection_end);
     3248        li = EDIT_EM_LineIndex(es, l);
     3249        x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP));
     3250        vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     3251        if (l >= es->y_offset + vlc)
     3252            dy = l - vlc + 1 - es->y_offset;
     3253        if (l < es->y_offset)
     3254            dy = l - es->y_offset;
     3255        ww = es->format_rect.right - es->format_rect.left;
     3256        if (x < es->format_rect.left)
     3257            dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
     3258        if (x > es->format_rect.right)
     3259            dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
     3260        if (dy || dx)
     3261        {
     3262            /* check if we are going to move too far */
     3263            if(es->x_offset + dx + ww > es->text_width)
     3264            dx = es->text_width - ww - es->x_offset;
     3265            if(dx || dy)
     3266            EDIT_EM_LineScroll_internal(hwnd, es, dx, dy);
     3267        }
     3268    } else {
     3269        INT x;
     3270        INT goal;
     3271        INT format_width;
     3272
     3273        if (!(es->style & ES_AUTOHSCROLL))
     3274            return;
     3275
     3276        x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, FALSE));
     3277        format_width = es->format_rect.right - es->format_rect.left;
     3278        if (x < es->format_rect.left) {
     3279            goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
     3280            do {
     3281                es->x_offset--;
     3282                x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, FALSE));
     3283            } while ((x < goal) && es->x_offset);
     3284            /* FIXME: use ScrollWindow() somehow to improve performance */
     3285            EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3286        } else if (x > es->format_rect.right) {
     3287            INT x_last;
     3288            INT len = strlenW(es->text);
     3289            goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
     3290            do {
     3291                es->x_offset++;
     3292                x = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, es->selection_end, FALSE));
     3293                x_last = SLOWORD(EDIT_EM_PosFromChar(hwnd, es, len, FALSE));
     3294            } while ((x > goal) && (x_last > es->format_rect.right));
     3295            /* FIXME: use ScrollWindow() somehow to improve performance */
     3296            EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3297        }
     3298    }
    32663299
    32673300    if(es->flags & EF_FOCUSED)
    3268         EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
    3269 }
    3270 
    3271 
    3272 /*********************************************************************
    3273  *
    3274  *      EM_SETHANDLE
    3275  *
    3276  *      FIXME:  ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
     3301    EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
     3302}
     3303
     3304
     3305/*********************************************************************
     3306 *
     3307 *  EM_SETHANDLE
     3308 *
     3309 *  FIXME:  ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
    32773310 *
    32783311 */
     
    32813314    HINSTANCE hInstance = GetWindowLongA( hwnd, GWL_HINSTANCE );
    32823315
    3283         if (!(es->style & ES_MULTILINE))
    3284                 return;
    3285 
    3286         if (!hloc) {
    3287                 WARN("called with NULL handle\n");
    3288                 return;
    3289         }
    3290 
    3291         EDIT_UnlockBuffer(hwnd, es, TRUE);
     3316    if (!(es->style & ES_MULTILINE))
     3317        return;
     3318
     3319    if (!hloc) {
     3320        WARN("called with NULL handle\n");
     3321        return;
     3322    }
     3323
     3324    EDIT_UnlockBuffer(hwnd, es, TRUE);
    32923325
    32933326#ifndef __WIN32OS2__
    3294         if(es->hloc16)
    3295         {
    3296             LOCAL_Free(hInstance, es->hloc16);
    3297             es->hloc16 = (HLOCAL16)NULL;
    3298         }
     3327    if(es->hloc16)
     3328    {
     3329        LOCAL_Free(hInstance, es->hloc16);
     3330        es->hloc16 = (HLOCAL16)NULL;
     3331    }
    32993332#endif
    3300         if(es->is_unicode)
    3301         {
    3302             if(es->hloc32A)
    3303             {
    3304                 LocalFree(es->hloc32A);
    3305                 es->hloc32A = (HLOCAL)NULL;
    3306             }
    3307             es->hloc32W = hloc;
    3308         }
    3309         else
    3310         {
    3311             INT countW, countA;
    3312             HLOCAL hloc32W_new;
    3313             WCHAR *textW;
    3314             CHAR *textA;
    3315 
    3316             countA = LocalSize(hloc);
    3317             textA = LocalLock(hloc);
    3318             countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
    3319             if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR))))
    3320             {
    3321                 ERR("Could not allocate new unicode buffer\n");
    3322                 return;
    3323             }
    3324             textW = LocalLock(hloc32W_new);
    3325             MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW);
    3326             LocalUnlock(hloc32W_new);
    3327             LocalUnlock(hloc);
    3328 
    3329             if(es->hloc32W)
    3330                 LocalFree(es->hloc32W);
    3331 
    3332             es->hloc32W = hloc32W_new;
    3333             es->hloc32A = hloc;
    3334         }
    3335 
    3336         es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
    3337 
    3338         EDIT_LockBuffer(hwnd, es);
    3339 
    3340         es->x_offset = es->y_offset = 0;
    3341         es->selection_start = es->selection_end = 0;
    3342         EDIT_EM_EmptyUndoBuffer(es);
    3343         es->flags &= ~EF_MODIFIED;
    3344         es->flags &= ~EF_UPDATE;
    3345         EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
    3346         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3347         EDIT_EM_ScrollCaret(hwnd, es);
    3348         /* force scroll info update */
    3349         EDIT_UpdateScrollInfo(hwnd, es);
     3333    if(es->is_unicode)
     3334    {
     3335        if(es->hloc32A)
     3336        {
     3337        LocalFree(es->hloc32A);
     3338        es->hloc32A = (HLOCAL)NULL;
     3339        }
     3340        es->hloc32W = hloc;
     3341    }
     3342    else
     3343    {
     3344        INT countW, countA;
     3345        HLOCAL hloc32W_new;
     3346        WCHAR *textW;
     3347        CHAR *textA;
     3348
     3349        countA = LocalSize(hloc);
     3350        textA = LocalLock(hloc);
     3351        countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
     3352        if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR))))
     3353        {
     3354        ERR("Could not allocate new unicode buffer\n");
     3355        return;
     3356        }
     3357        textW = LocalLock(hloc32W_new);
     3358        MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW);
     3359        LocalUnlock(hloc32W_new);
     3360        LocalUnlock(hloc);
     3361
     3362        if(es->hloc32W)
     3363        LocalFree(es->hloc32W);
     3364
     3365        es->hloc32W = hloc32W_new;
     3366        es->hloc32A = hloc;
     3367    }
     3368
     3369    es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
     3370
     3371    EDIT_LockBuffer(hwnd, es);
     3372
     3373    es->x_offset = es->y_offset = 0;
     3374    es->selection_start = es->selection_end = 0;
     3375    EDIT_EM_EmptyUndoBuffer(es);
     3376    es->flags &= ~EF_MODIFIED;
     3377    es->flags &= ~EF_UPDATE;
     3378    EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
     3379    EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3380    EDIT_EM_ScrollCaret(hwnd, es);
     3381    /* force scroll info update */
     3382    EDIT_UpdateScrollInfo(hwnd, es);
    33503383}
    33513384
     
    33543387/*********************************************************************
    33553388 *
    3356  *      EM_SETHANDLE16
    3357  *
    3358  *      FIXME:  ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
     3389 *  EM_SETHANDLE16
     3390 *
     3391 *  FIXME:  ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
    33593392 *
    33603393 */
     
    33623395{
    33633396    HINSTANCE hInstance = GetWindowLongA( hwnd, GWL_HINSTANCE );
    3364         INT countW, countA;
    3365         HLOCAL hloc32W_new;
    3366         WCHAR *textW;
    3367         CHAR *textA;
    3368 
    3369         if (!(es->style & ES_MULTILINE))
    3370                 return;
    3371 
    3372         if (!hloc) {
    3373                 WARN("called with NULL handle\n");
    3374                 return;
    3375         }
    3376 
    3377         EDIT_UnlockBuffer(hwnd, es, TRUE);
    3378 
    3379         if(es->hloc32A)
    3380         {
    3381             LocalFree(es->hloc32A);
    3382             es->hloc32A = (HLOCAL)NULL;
    3383         }
    3384 
    3385         countA = LOCAL_Size(hInstance, hloc);
    3386         textA = LOCAL_Lock(hInstance, hloc);
    3387         countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
    3388         if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR))))
    3389         {
    3390             ERR("Could not allocate new unicode buffer\n");
    3391             return;
    3392         }
    3393         textW = LocalLock(hloc32W_new);
    3394         MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW);
    3395         LocalUnlock(hloc32W_new);
    3396         LOCAL_Unlock(hInstance, hloc);
    3397 
    3398         if(es->hloc32W)
    3399             LocalFree(es->hloc32W);
    3400 
    3401         es->hloc32W = hloc32W_new;
    3402         es->hloc16 = hloc;
    3403 
    3404         es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
    3405 
    3406         EDIT_LockBuffer(hwnd, es);
    3407 
    3408         es->x_offset = es->y_offset = 0;
    3409         es->selection_start = es->selection_end = 0;
    3410         EDIT_EM_EmptyUndoBuffer(es);
    3411         es->flags &= ~EF_MODIFIED;
    3412         es->flags &= ~EF_UPDATE;
    3413         EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
    3414         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3415         EDIT_EM_ScrollCaret(hwnd, es);
    3416         /* force scroll info update */
    3417         EDIT_UpdateScrollInfo(hwnd, es);
     3397    INT countW, countA;
     3398    HLOCAL hloc32W_new;
     3399    WCHAR *textW;
     3400    CHAR *textA;
     3401
     3402    if (!(es->style & ES_MULTILINE))
     3403        return;
     3404
     3405    if (!hloc) {
     3406        WARN("called with NULL handle\n");
     3407        return;
     3408    }
     3409
     3410    EDIT_UnlockBuffer(hwnd, es, TRUE);
     3411
     3412    if(es->hloc32A)
     3413    {
     3414        LocalFree(es->hloc32A);
     3415        es->hloc32A = (HLOCAL)NULL;
     3416    }
     3417
     3418    countA = LOCAL_Size(hInstance, hloc);
     3419    textA = LOCAL_Lock(hInstance, hloc);
     3420    countW = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
     3421    if(!(hloc32W_new = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, countW * sizeof(WCHAR))))
     3422    {
     3423        ERR("Could not allocate new unicode buffer\n");
     3424        return;
     3425    }
     3426    textW = LocalLock(hloc32W_new);
     3427    MultiByteToWideChar(CP_ACP, 0, textA, countA, textW, countW);
     3428    LocalUnlock(hloc32W_new);
     3429    LOCAL_Unlock(hInstance, hloc);
     3430
     3431    if(es->hloc32W)
     3432        LocalFree(es->hloc32W);
     3433
     3434    es->hloc32W = hloc32W_new;
     3435    es->hloc16 = hloc;
     3436
     3437    es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
     3438
     3439    EDIT_LockBuffer(hwnd, es);
     3440
     3441    es->x_offset = es->y_offset = 0;
     3442    es->selection_start = es->selection_end = 0;
     3443    EDIT_EM_EmptyUndoBuffer(es);
     3444    es->flags &= ~EF_MODIFIED;
     3445    es->flags &= ~EF_UPDATE;
     3446    EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
     3447    EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3448    EDIT_EM_ScrollCaret(hwnd, es);
     3449    /* force scroll info update */
     3450    EDIT_UpdateScrollInfo(hwnd, es);
    34183451}
    34193452#endif
     
    34213454/*********************************************************************
    34223455 *
    3423  *      EM_SETLIMITTEXT
    3424  *
    3425  *      FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF
    3426  *      However, the windows version is not complied to yet in all of edit.c
     3456 *  EM_SETLIMITTEXT
     3457 *
     3458 *  FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF
     3459 *  However, the windows version is not complied to yet in all of edit.c
    34273460 *
    34283461 */
    34293462static void EDIT_EM_SetLimitText(EDITSTATE *es, INT limit)
    34303463{
    3431         if (es->style & ES_MULTILINE) {
    3432                 if (limit)
    3433                         es->buffer_limit = min(limit, BUFLIMIT_MULTI);
    3434                 else
    3435                         es->buffer_limit = BUFLIMIT_MULTI;
    3436         } else {
    3437                 if (limit)
    3438                         es->buffer_limit = min(limit, BUFLIMIT_SINGLE);
    3439                 else
    3440                         es->buffer_limit = BUFLIMIT_SINGLE;
    3441         }
    3442 }
    3443 
    3444 
    3445 /*********************************************************************
    3446  *
    3447  *      EM_SETMARGINS
     3464    if (es->style & ES_MULTILINE) {
     3465        if (limit)
     3466            es->buffer_limit = min(limit, BUFLIMIT_MULTI);
     3467        else
     3468            es->buffer_limit = BUFLIMIT_MULTI;
     3469    } else {
     3470        if (limit)
     3471            es->buffer_limit = min(limit, BUFLIMIT_SINGLE);
     3472        else
     3473            es->buffer_limit = BUFLIMIT_SINGLE;
     3474    }
     3475}
     3476
     3477
     3478/*********************************************************************
     3479 *
     3480 *  EM_SETMARGINS
    34483481 *
    34493482 * EC_USEFONTINFO is used as a left or right value i.e. lParam and not as an
     
    34533486 */
    34543487static void EDIT_EM_SetMargins(EDITSTATE *es, INT action,
    3455                                INT left, INT right)
    3456 {
    3457         if (action & EC_LEFTMARGIN) {
    3458                 if (left != EC_USEFONTINFO)
    3459                         es->left_margin = left;
    3460                 else
    3461                         es->left_margin = es->char_width / 3;
    3462         }
    3463 
    3464         if (action & EC_RIGHTMARGIN) {
    3465                 if (right != EC_USEFONTINFO)
    3466                         es->right_margin = right;
    3467                 else
    3468                         es->right_margin = es->char_width / 3;
    3469         }
    3470         TRACE("left=%d, right=%d\n", es->left_margin, es->right_margin);
    3471 }
    3472 
    3473 
    3474 /*********************************************************************
    3475  *
    3476  *      EM_SETPASSWORDCHAR
     3488                   INT left, INT right)
     3489{
     3490    if (action & EC_LEFTMARGIN) {
     3491        if (left != EC_USEFONTINFO)
     3492            es->left_margin = left;
     3493        else
     3494            es->left_margin = es->char_width / 3;
     3495    }
     3496
     3497    if (action & EC_RIGHTMARGIN) {
     3498        if (right != EC_USEFONTINFO)
     3499            es->right_margin = right;
     3500        else
     3501            es->right_margin = es->char_width / 3;
     3502    }
     3503    TRACE("left=%d, right=%d\n", es->left_margin, es->right_margin);
     3504}
     3505
     3506
     3507/*********************************************************************
     3508 *
     3509 *  EM_SETPASSWORDCHAR
    34773510 *
    34783511 */
     
    34813514    LONG style;
    34823515
    3483         if (es->style & ES_MULTILINE)
    3484                 return;
    3485 
    3486         if (es->password_char == c)
    3487                 return;
     3516    if (es->style & ES_MULTILINE)
     3517        return;
     3518
     3519    if (es->password_char == c)
     3520        return;
    34883521
    34893522        style = GetWindowLongA( hwnd, GWL_STYLE );
    3490         es->password_char = c;
    3491         if (c) {
     3523    es->password_char = c;
     3524    if (c) {
    34923525            SetWindowLongA( hwnd, GWL_STYLE, style | ES_PASSWORD );
    34933526            es->style |= ES_PASSWORD;
    3494         } else {
     3527    } else {
    34953528            SetWindowLongA( hwnd, GWL_STYLE, style & ~ES_PASSWORD );
    34963529            es->style &= ~ES_PASSWORD;
    3497         }
    3498         EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3499 }
    3500 
    3501 
    3502 /*********************************************************************
    3503  *
    3504  *      EDIT_EM_SetSel
    3505  *
    3506  *      note:   unlike the specs say: the order of start and end
    3507  *              _is_ preserved in Windows.  (i.e. start can be > end)
    3508  *              In other words: this handler is OK
     3530    }
     3531    EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3532}
     3533
     3534
     3535/*********************************************************************
     3536 *
     3537 *  EDIT_EM_SetSel
     3538 *
     3539 *  note:   unlike the specs say: the order of start and end
     3540 *      _is_ preserved in Windows.  (i.e. start can be > end)
     3541 *      In other words: this handler is OK
    35093542 *
    35103543 */
    35113544static void EDIT_EM_SetSel(HWND hwnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
    35123545{
    3513         UINT old_start = es->selection_start;
    3514         UINT old_end = es->selection_end;
    3515         UINT len = strlenW(es->text);
    3516 
    3517         if (start == (UINT)-1) {
    3518                 start = es->selection_end;
    3519                 end = es->selection_end;
    3520         } else {
    3521                 start = min(start, len);
    3522                 end = min(end, len);
    3523         }
    3524         es->selection_start = start;
    3525         es->selection_end = end;
    3526         if (after_wrap)
    3527                 es->flags |= EF_AFTER_WRAP;
    3528         else
    3529                 es->flags &= ~EF_AFTER_WRAP;
     3546    UINT old_start = es->selection_start;
     3547    UINT old_end = es->selection_end;
     3548    UINT len = strlenW(es->text);
     3549
     3550    if (start == (UINT)-1) {
     3551        start = es->selection_end;
     3552        end = es->selection_end;
     3553    } else {
     3554        start = min(start, len);
     3555        end = min(end, len);
     3556    }
     3557    es->selection_start = start;
     3558    es->selection_end = end;
     3559    if (after_wrap)
     3560        es->flags |= EF_AFTER_WRAP;
     3561    else
     3562        es->flags &= ~EF_AFTER_WRAP;
    35303563/* This is a little bit more efficient than before, not sure if it can be improved. FIXME? */
    35313564        ORDER_UINT(start, end);
     
    35333566        ORDER_UINT(start, old_start);
    35343567        ORDER_UINT(old_start, old_end);
    3535         if (end != old_start)
     3568    if (end != old_start)
    35363569        {
    35373570/*
     
    35523585                EDIT_InvalidateText(hwnd, es, end, old_end);
    35533586            }
    3554         }
     3587    }
    35553588        else EDIT_InvalidateText(hwnd, es, start, old_end);
    35563589}
     
    35593592/*********************************************************************
    35603593 *
    3561  *      EM_SETTABSTOPS
     3594 *  EM_SETTABSTOPS
    35623595 *
    35633596 */
    35643597static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs)
    35653598{
    3566         if (!(es->style & ES_MULTILINE))
    3567                 return FALSE;
    3568         if (es->tabs)
    3569                 HeapFree(GetProcessHeap(), 0, es->tabs);
    3570         es->tabs_count = count;
    3571         if (!count)
    3572                 es->tabs = NULL;
    3573         else {
    3574                 es->tabs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
    3575                 memcpy(es->tabs, tabs, count * sizeof(INT));
    3576         }
    3577         return TRUE;
    3578 }
    3579 
    3580 
    3581 /*********************************************************************
    3582  *
    3583  *      EM_SETTABSTOPS16
     3599    if (!(es->style & ES_MULTILINE))
     3600        return FALSE;
     3601    if (es->tabs)
     3602        HeapFree(GetProcessHeap(), 0, es->tabs);
     3603    es->tabs_count = count;
     3604    if (!count)
     3605        es->tabs = NULL;
     3606    else {
     3607        es->tabs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
     3608        memcpy(es->tabs, tabs, count * sizeof(INT));
     3609    }
     3610    return TRUE;
     3611}
     3612
     3613
     3614/*********************************************************************
     3615 *
     3616 *  EM_SETTABSTOPS16
    35843617 *
    35853618 */
    35863619static BOOL EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs)
    35873620{
    3588         if (!(es->style & ES_MULTILINE))
    3589                 return FALSE;
    3590         if (es->tabs)
    3591                 HeapFree(GetProcessHeap(), 0, es->tabs);
    3592         es->tabs_count = count;
    3593         if (!count)
    3594                 es->tabs = NULL;
    3595         else {
    3596                 INT i;
    3597                 es->tabs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
    3598                 for (i = 0 ; i < count ; i++)
    3599                         es->tabs[i] = *tabs++;
    3600         }
    3601         return TRUE;
    3602 }
    3603 
    3604 
    3605 /*********************************************************************
    3606  *
    3607  *      EM_SETWORDBREAKPROC
     3621    if (!(es->style & ES_MULTILINE))
     3622        return FALSE;
     3623    if (es->tabs)
     3624        HeapFree(GetProcessHeap(), 0, es->tabs);
     3625    es->tabs_count = count;
     3626    if (!count)
     3627        es->tabs = NULL;
     3628    else {
     3629        INT i;
     3630        es->tabs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
     3631        for (i = 0 ; i < count ; i++)
     3632            es->tabs[i] = *tabs++;
     3633    }
     3634    return TRUE;
     3635}
     3636
     3637
     3638/*********************************************************************
     3639 *
     3640 *  EM_SETWORDBREAKPROC
    36083641 *
    36093642 */
    36103643static void EDIT_EM_SetWordBreakProc(HWND hwnd, EDITSTATE *es, LPARAM lParam)
    36113644{
    3612         if (es->word_break_proc == (void *)lParam)
    3613                 return;
    3614 
    3615         es->word_break_proc = (void *)lParam;
    3616         es->word_break_proc16 = NULL;
    3617 
    3618         if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
    3619                 EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
    3620                 EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3621         }
     3645    if (es->word_break_proc == (void *)lParam)
     3646        return;
     3647
     3648    es->word_break_proc = (void *)lParam;
     3649    es->word_break_proc16 = NULL;
     3650
     3651    if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
     3652        EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
     3653        EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3654    }
    36223655}
    36233656
     
    36263659/*********************************************************************
    36273660 *
    3628  *      EM_SETWORDBREAKPROC16
     3661 *  EM_SETWORDBREAKPROC16
    36293662 *
    36303663 */
    36313664static void EDIT_EM_SetWordBreakProc16(HWND hwnd, EDITSTATE *es, EDITWORDBREAKPROC16 wbp)
    36323665{
    3633         if (es->word_break_proc16 == wbp)
    3634                 return;
    3635 
    3636         es->word_break_proc = NULL;
    3637         es->word_break_proc16 = wbp;
    3638         if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
    3639                 EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
    3640                 EDIT_UpdateText(hwnd, es, NULL, TRUE);
    3641         }
     3666    if (es->word_break_proc16 == wbp)
     3667        return;
     3668
     3669    es->word_break_proc = NULL;
     3670    es->word_break_proc16 = wbp;
     3671    if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
     3672        EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
     3673        EDIT_UpdateText(hwnd, es, NULL, TRUE);
     3674    }
    36423675}
    36433676#endif
     
    36453678/*********************************************************************
    36463679 *
    3647  *      EM_UNDO / WM_UNDO
     3680 *  EM_UNDO / WM_UNDO
    36483681 *
    36493682 */
    36503683static BOOL EDIT_EM_Undo(HWND hwnd, EDITSTATE *es)
    36513684{
    3652         INT ulength;
    3653         LPWSTR utext;
    3654 
    3655         /* Protect read-only edit control from modification */
    3656         if(es->style & ES_READONLY)
    3657             return FALSE;
    3658 
    3659         ulength = strlenW(es->undo_text);
    3660         utext = HeapAlloc(GetProcessHeap(), 0, (ulength + 1) * sizeof(WCHAR));
    3661 
    3662         strcpyW(utext, es->undo_text);
    3663 
    3664         TRACE("before UNDO:insertion length = %d, deletion buffer = %s\n",
    3665                      es->undo_insert_count, debugstr_w(utext));
    3666 
    3667         EDIT_EM_SetSel(hwnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
    3668         EDIT_EM_EmptyUndoBuffer(es);
    3669         EDIT_EM_ReplaceSel(hwnd, es, TRUE, utext, FALSE);
    3670         EDIT_EM_SetSel(hwnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
     3685    INT ulength;
     3686    LPWSTR utext;
     3687
     3688    /* Protect read-only edit control from modification */
     3689    if(es->style & ES_READONLY)
     3690        return FALSE;
     3691
     3692    ulength = strlenW(es->undo_text);
     3693    utext = HeapAlloc(GetProcessHeap(), 0, (ulength + 1) * sizeof(WCHAR));
     3694
     3695    strcpyW(utext, es->undo_text);
     3696
     3697    TRACE("before UNDO:insertion length = %d, deletion buffer = %s\n",
     3698             es->undo_insert_count, debugstr_w(utext));
     3699
     3700    EDIT_EM_SetSel(hwnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
     3701    EDIT_EM_EmptyUndoBuffer(es);
     3702    EDIT_EM_ReplaceSel(hwnd, es, TRUE, utext, FALSE);
     3703    EDIT_EM_SetSel(hwnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
    36713704        /* send the notification after the selection start and end are set */
    36723705        EDIT_NOTIFY_PARENT(hwnd, es, EN_CHANGE, "EN_CHANGE");
    3673         EDIT_EM_ScrollCaret(hwnd, es);
    3674         HeapFree(GetProcessHeap(), 0, utext);
    3675 
    3676         TRACE("after UNDO:insertion length = %d, deletion buffer = %s\n",
    3677                         es->undo_insert_count, debugstr_w(es->undo_text));
    3678         return TRUE;
    3679 }
    3680 
    3681 
    3682 /*********************************************************************
    3683  *
    3684  *      WM_CHAR
     3706    EDIT_EM_ScrollCaret(hwnd, es);
     3707    HeapFree(GetProcessHeap(), 0, utext);
     3708
     3709    TRACE("after UNDO:insertion length = %d, deletion buffer = %s\n",
     3710            es->undo_insert_count, debugstr_w(es->undo_text));
     3711    return TRUE;
     3712}
     3713
     3714
     3715/*********************************************************************
     3716 *
     3717 *  WM_CHAR
    36853718 *
    36863719 */
     
    36893722        BOOL control;
    36903723
    3691         /* Protect read-only edit control from modification */
    3692         if(es->style & ES_READONLY)
    3693             return;
    3694 
    3695         control = GetKeyState(VK_CONTROL) & 0x8000;
    3696 
    3697         switch (c) {
    3698         case '\r':
    3699             /* If the edit doesn't want the return and it's not a multiline edit, do nothing */
    3700             if(!(es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN))
    3701                 break;
    3702         case '\n':
    3703                 if (es->style & ES_MULTILINE) {
    3704                         if (es->style & ES_READONLY) {
    3705                                 EDIT_MoveHome(hwnd, es, FALSE);
    3706                                 EDIT_MoveDown_ML(hwnd, es, FALSE);
    3707                         } else {
    3708                                 static const WCHAR cr_lfW[] = {'\r','\n',0};
    3709                                 EDIT_EM_ReplaceSel(hwnd, es, TRUE, cr_lfW, TRUE);
    3710                         }
    3711                 }
    3712                 break;
    3713         case '\t':
    3714                 if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
    3715                 {
    3716                         static const WCHAR tabW[] = {'\t',0};
    3717                         EDIT_EM_ReplaceSel(hwnd, es, TRUE, tabW, TRUE);
    3718                 }
    3719                 break;
    3720         case VK_BACK:
    3721                 if (!(es->style & ES_READONLY) && !control) {
    3722                         if (es->selection_start != es->selection_end)
    3723                                 EDIT_WM_Clear(hwnd, es);
    3724                         else {
    3725                                 /* delete character left of caret */
    3726                                 EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
    3727                                 EDIT_MoveBackward(hwnd, es, TRUE);
    3728                                 EDIT_WM_Clear(hwnd, es);
    3729                         }
    3730                 }
    3731                 break;
    3732         case 0x03: /* ^C */
    3733                 SendMessageW(hwnd, WM_COPY, 0, 0);
    3734                 break;
    3735         case 0x16: /* ^V */
    3736                 SendMessageW(hwnd, WM_PASTE, 0, 0);
    3737                 break;
    3738         case 0x18: /* ^X */
    3739                 SendMessageW(hwnd, WM_CUT, 0, 0);
    3740                 break;
    3741 
    3742         default:
    3743                 if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127)) {
    3744                         WCHAR str[2];
    3745                         str[0] = c;
    3746                         str[1] = '\0';
    3747                         EDIT_EM_ReplaceSel(hwnd, es, TRUE, str, TRUE);
    3748                 }
    3749                 break;
    3750         }
    3751 }
    3752 
    3753 
    3754 /*********************************************************************
    3755  *
    3756  *      WM_COMMAND
     3724    /* Protect read-only edit control from modification */
     3725    if(es->style & ES_READONLY)
     3726        return;
     3727
     3728    control = GetKeyState(VK_CONTROL) & 0x8000;
     3729
     3730    switch (c) {
     3731    case '\r':
     3732        /* If the edit doesn't want the return and it's not a multiline edit, do nothing */
     3733        if(!(es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN))
     3734        break;
     3735    case '\n':
     3736        if (es->style & ES_MULTILINE) {
     3737            if (es->style & ES_READONLY) {
     3738                EDIT_MoveHome(hwnd, es, FALSE);
     3739                EDIT_MoveDown_ML(hwnd, es, FALSE);
     3740            } else {
     3741                static const WCHAR cr_lfW[] = {'\r','\n',0};
     3742                EDIT_EM_ReplaceSel(hwnd, es, TRUE, cr_lfW, TRUE);
     3743            }
     3744        }
     3745        break;
     3746    case '\t':
     3747        if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
     3748        {
     3749            static const WCHAR tabW[] = {'\t',0};
     3750            EDIT_EM_ReplaceSel(hwnd, es, TRUE, tabW, TRUE);
     3751        }
     3752        break;
     3753    case VK_BACK:
     3754        if (!(es->style & ES_READONLY) && !control) {
     3755            if (es->selection_start != es->selection_end)
     3756                EDIT_WM_Clear(hwnd, es);
     3757            else {
     3758                /* delete character left of caret */
     3759                EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     3760                EDIT_MoveBackward(hwnd, es, TRUE);
     3761                EDIT_WM_Clear(hwnd, es);
     3762            }
     3763        }
     3764        break;
     3765    case 0x03: /* ^C */
     3766        SendMessageW(hwnd, WM_COPY, 0, 0);
     3767        break;
     3768    case 0x16: /* ^V */
     3769        SendMessageW(hwnd, WM_PASTE, 0, 0);
     3770        break;
     3771    case 0x18: /* ^X */
     3772        SendMessageW(hwnd, WM_CUT, 0, 0);
     3773        break;
     3774
     3775    default:
     3776        if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127)) {
     3777            WCHAR str[2];
     3778            str[0] = c;
     3779            str[1] = '\0';
     3780            EDIT_EM_ReplaceSel(hwnd, es, TRUE, str, TRUE);
     3781        }
     3782        break;
     3783    }
     3784}
     3785
     3786
     3787/*********************************************************************
     3788 *
     3789 *  WM_COMMAND
    37573790 *
    37583791 */
    37593792static void EDIT_WM_Command(HWND hwnd, EDITSTATE *es, INT code, INT id, HWND control)
    37603793{
    3761         if (code || control)
    3762                 return;
    3763 
    3764         switch (id) {
    3765                 case EM_UNDO:
    3766                         EDIT_EM_Undo(hwnd, es);
    3767                         break;
    3768                 case WM_CUT:
    3769                         EDIT_WM_Cut(hwnd, es);
    3770                         break;
    3771                 case WM_COPY:
    3772                         EDIT_WM_Copy(hwnd, es);
    3773                         break;
    3774                 case WM_PASTE:
    3775                         EDIT_WM_Paste(hwnd, es);
    3776                         break;
    3777                 case WM_CLEAR:
    3778                         EDIT_WM_Clear(hwnd, es);
    3779                         break;
    3780                 case EM_SETSEL:
    3781                         EDIT_EM_SetSel(hwnd, es, 0, (UINT)-1, FALSE);
    3782                         EDIT_EM_ScrollCaret(hwnd, es);
    3783                         break;
    3784                 default:
    3785                         ERR("unknown menu item, please report\n");
    3786                         break;
    3787         }
    3788 }
    3789 
    3790 
    3791 /*********************************************************************
    3792  *
    3793  *      WM_CONTEXTMENU
    3794  *
    3795  *      Note: the resource files resource/sysres_??.rc cannot define a
    3796  *              single popup menu.  Hence we use a (dummy) menubar
    3797  *              containing the single popup menu as its first item.
    3798  *
    3799  *      FIXME: the message identifiers have been chosen arbitrarily,
    3800  *              hence we use MF_BYPOSITION.
    3801  *              We might as well use the "real" values (anybody knows ?)
    3802  *              The menu definition is in resources/sysres_??.rc.
    3803  *              Once these are OK, we better use MF_BYCOMMAND here
    3804  *              (as we do in EDIT_WM_Command()).
     3794    if (code || control)
     3795        return;
     3796
     3797    switch (id) {
     3798        case EM_UNDO:
     3799            EDIT_EM_Undo(hwnd, es);
     3800            break;
     3801        case WM_CUT:
     3802            EDIT_WM_Cut(hwnd, es);
     3803            break;
     3804        case WM_COPY:
     3805            EDIT_WM_Copy(hwnd, es);
     3806            break;
     3807        case WM_PASTE:
     3808            EDIT_WM_Paste(hwnd, es);
     3809            break;
     3810        case WM_CLEAR:
     3811            EDIT_WM_Clear(hwnd, es);
     3812            break;
     3813        case EM_SETSEL:
     3814            EDIT_EM_SetSel(hwnd, es, 0, (UINT)-1, FALSE);
     3815            EDIT_EM_ScrollCaret(hwnd, es);
     3816            break;
     3817        default:
     3818            ERR("unknown menu item, please report\n");
     3819            break;
     3820    }
     3821}
     3822
     3823
     3824/*********************************************************************
     3825 *
     3826 *  WM_CONTEXTMENU
     3827 *
     3828 *  Note: the resource files resource/sysres_??.rc cannot define a
     3829 *      single popup menu.  Hence we use a (dummy) menubar
     3830 *      containing the single popup menu as its first item.
     3831 *
     3832 *  FIXME: the message identifiers have been chosen arbitrarily,
     3833 *      hence we use MF_BYPOSITION.
     3834 *      We might as well use the "real" values (anybody knows ?)
     3835 *      The menu definition is in resources/sysres_??.rc.
     3836 *      Once these are OK, we better use MF_BYCOMMAND here
     3837 *      (as we do in EDIT_WM_Command()).
    38053838 *
    38063839 */
    38073840static void EDIT_WM_ContextMenu(HWND hwnd, EDITSTATE *es, INT x, INT y)
    38083841{
    3809         HMENU menu = LoadMenuA(GetModuleHandleA("USER32"), "EDITMENU");
    3810         HMENU popup = GetSubMenu(menu, 0);
    3811         UINT start = es->selection_start;
    3812         UINT end = es->selection_end;
    3813 
    3814         ORDER_UINT(start, end);
    3815 
    3816         /* undo */
    3817         EnableMenuItem(popup, 0, MF_BYPOSITION | (EDIT_EM_CanUndo(es) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
    3818         /* cut */
    3819         EnableMenuItem(popup, 2, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
    3820         /* copy */
    3821         EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
    3822         /* paste */
    3823         EnableMenuItem(popup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_UNICODETEXT) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
    3824         /* delete */
    3825         EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
    3826         /* select all */
    3827         EnableMenuItem(popup, 7, MF_BYPOSITION | (start || (end != strlenW(es->text)) ? MF_ENABLED : MF_GRAYED));
    3828 
    3829         TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, hwnd, NULL);
    3830         DestroyMenu(menu);
    3831 }
    3832 
    3833 
    3834 /*********************************************************************
    3835  *
    3836  *      WM_COPY
     3842    HMENU menu = LoadMenuA(GetModuleHandleA("USER32"), "EDITMENU");
     3843    HMENU popup = GetSubMenu(menu, 0);
     3844    UINT start = es->selection_start;
     3845    UINT end = es->selection_end;
     3846
     3847    ORDER_UINT(start, end);
     3848
     3849    /* undo */
     3850    EnableMenuItem(popup, 0, MF_BYPOSITION | (EDIT_EM_CanUndo(es) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
     3851    /* cut */
     3852    EnableMenuItem(popup, 2, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
     3853    /* copy */
     3854    EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
     3855    /* paste */
     3856    EnableMenuItem(popup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_UNICODETEXT) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
     3857    /* delete */
     3858    EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
     3859    /* select all */
     3860    EnableMenuItem(popup, 7, MF_BYPOSITION | (start || (end != strlenW(es->text)) ? MF_ENABLED : MF_GRAYED));
     3861
     3862    TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, hwnd, NULL);
     3863    DestroyMenu(menu);
     3864}
     3865
     3866
     3867/*********************************************************************
     3868 *
     3869 *  WM_COPY
    38373870 *
    38383871 */
    38393872static void EDIT_WM_Copy(HWND hwnd, EDITSTATE *es)
    38403873{
    3841         INT s = es->selection_start;
    3842         INT e = es->selection_end;
    3843         HGLOBAL hdst;
    3844         LPWSTR dst;
    3845 
    3846         if (e == s)
    3847                 return;
    3848         ORDER_INT(s, e);
    3849         hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)(e - s + 1) * sizeof(WCHAR));
    3850         dst = GlobalLock(hdst);
    3851         strncpyW(dst, es->text + s, e - s);
    3852         dst[e - s] = 0; /* ensure 0 termination */
    3853         TRACE("%s\n", debugstr_w(dst));
    3854         GlobalUnlock(hdst);
    3855         OpenClipboard(hwnd);
    3856         EmptyClipboard();
    3857         SetClipboardData(CF_UNICODETEXT, hdst);
    3858         CloseClipboard();
    3859 }
    3860 
    3861 
    3862 /*********************************************************************
    3863  *
    3864  *      WM_CREATE
     3874    INT s = es->selection_start;
     3875    INT e = es->selection_end;
     3876    HGLOBAL hdst;
     3877    LPWSTR dst;
     3878
     3879    if (e == s)
     3880        return;
     3881    ORDER_INT(s, e);
     3882    hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)(e - s + 1) * sizeof(WCHAR));
     3883    dst = GlobalLock(hdst);
     3884    strncpyW(dst, es->text + s, e - s);
     3885    dst[e - s ] = 0; /* ensure 0 termination */
     3886    TRACE("%s\n", debugstr_w(dst));
     3887
     3888    GlobalUnlock(hdst);
     3889    OpenClipboard(hwnd);
     3890    EmptyClipboard();
     3891    SetClipboardData(CF_UNICODETEXT, hdst);
     3892    CloseClipboard();
     3893}
     3894
     3895
     3896/*********************************************************************
     3897 *
     3898 *  WM_CREATE
    38653899 *
    38663900 */
    38673901static LRESULT EDIT_WM_Create(HWND hwnd, EDITSTATE *es, LPCWSTR name)
    38683902{
    3869         TRACE("%s\n", debugstr_w(name));
     3903    TRACE("%s\n", debugstr_w(name));
    38703904       /*
    3871         *       To initialize some final structure members, we call some helper
    3872         *       functions.  However, since the EDITSTATE is not consistent (i.e.
    3873         *       not fully initialized), we should be very careful which
    3874         *       functions can be called, and in what order.
     3905        *   To initialize some final structure members, we call some helper
     3906        *   functions.  However, since the EDITSTATE is not consistent (i.e.
     3907        *   not fully initialized), we should be very careful which
     3908        *   functions can be called, and in what order.
    38753909        */
    38763910        EDIT_WM_SetFont(hwnd, es, 0, FALSE);
     
    38783912
    38793913       if (name && *name) {
    3880            EDIT_EM_ReplaceSel(hwnd, es, FALSE, name, FALSE);
    3881            /* if we insert text to the editline, the text scrolls out
     3914       EDIT_EM_ReplaceSel(hwnd, es, FALSE, name, FALSE);
     3915       /* if we insert text to the editline, the text scrolls out
    38823916            * of the window, as the caret is placed after the insert
    38833917            * pos normally; thus we reset es->selection... to 0 and
    38843918            * update caret
    38853919            */
    3886            es->selection_start = es->selection_end = 0;
     3920       es->selection_start = es->selection_end = 0;
    38873921           /* send the notification after the selection start and end are set */
    38883922           EDIT_NOTIFY_PARENT(hwnd, es, EN_CHANGE, "EN_CHANGE");
    3889            EDIT_EM_ScrollCaret(hwnd, es);
     3923       EDIT_EM_ScrollCaret(hwnd, es);
    38903924       }
    38913925       /* force scroll info update */
     
    38973931/*********************************************************************
    38983932 *
    3899  *      WM_DESTROY
     3933 *  WM_DESTROY
    39003934 *
    39013935 */
     
    39033937{
    39043938    HINSTANCE hInstance = GetWindowLongA( hwnd, GWL_HINSTANCE );
    3905         LINEDEF *pc, *pp;
    3906 
    3907         if (es->hloc32W) {
    3908                 while (LocalUnlock(es->hloc32W)) ;
    3909                 LocalFree(es->hloc32W);
    3910         }
    3911         if (es->hloc32A) {
    3912                 while (LocalUnlock(es->hloc32A)) ;
    3913                 LocalFree(es->hloc32A);
    3914         }
     3939    LINEDEF *pc, *pp;
     3940
     3941    if (es->hloc32W) {
     3942        while (LocalUnlock(es->hloc32W)) ;
     3943        LocalFree(es->hloc32W);
     3944    }
     3945    if (es->hloc32A) {
     3946        while (LocalUnlock(es->hloc32A)) ;
     3947        LocalFree(es->hloc32A);
     3948    }
    39153949#ifndef __WIN32OS2__
    3916         if (es->hloc16) {
    3917                 while (LOCAL_Unlock(hInstance, es->hloc16)) ;
    3918                 LOCAL_Free(hInstance, es->hloc16);
    3919         }
     3950    if (es->hloc16) {
     3951        while (LOCAL_Unlock(hInstance, es->hloc16)) ;
     3952        LOCAL_Free(hInstance, es->hloc16);
     3953    }
    39203954#endif
    3921         pc = es->first_line_def;
    3922         while (pc)
    3923         {
    3924                 pp = pc->next;
    3925                 HeapFree(GetProcessHeap(), 0, pc);
    3926                 pc = pp;
    3927         }
     3955    pc = es->first_line_def;
     3956    while (pc)
     3957    {
     3958        pp = pc->next;
     3959        HeapFree(GetProcessHeap(), 0, pc);
     3960        pc = pp;
     3961    }
    39283962
    39293963        SetWindowLongA( hwnd, 0, 0 );
    3930         HeapFree(GetProcessHeap(), 0, es);
    3931 }
    3932 
    3933 
    3934 /*********************************************************************
    3935  *
    3936  *      WM_ERASEBKGND
     3964    HeapFree(GetProcessHeap(), 0, es);
     3965}
     3966
     3967
     3968/*********************************************************************
     3969 *
     3970 *  WM_ERASEBKGND
    39373971 *
    39383972 */
    39393973static LRESULT EDIT_WM_EraseBkGnd(HWND hwnd, EDITSTATE *es, HDC dc)
    39403974{
    3941         HBRUSH brush;
    3942         RECT rc;
     3975    HBRUSH brush;
     3976    RECT rc;
    39433977
    39443978        if ( get_app_version() >= 0x40000 &&(
     
    39513985                brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
    39523986
    3953         GetClientRect(hwnd, &rc);
    3954         IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
    3955         GetClipBox(dc, &rc);
    3956         /*
    3957          *      FIXME:  specs say that we should UnrealizeObject() the brush,
    3958          *              but the specs of UnrealizeObject() say that we shouldn't
    3959          *              unrealize a stock object.  The default brush that
    3960          *              DefWndProc() returns is ... a stock object.
    3961         */
    3962         FillRect(dc, &rc, brush);
    3963         return -1;
    3964 }
    3965 
    3966 
    3967 /*********************************************************************
    3968  *
    3969  *      WM_GETTEXT
     3987    GetClientRect(hwnd, &rc);
     3988    IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
     3989    GetClipBox(dc, &rc);
     3990    /*
     3991     *  FIXME:  specs say that we should UnrealizeObject() the brush,
     3992     *      but the specs of UnrealizeObject() say that we shouldn't
     3993     *      unrealize a stock object.  The default brush that
     3994     *      DefWndProc() returns is ... a stock object.
     3995    */
     3996    FillRect(dc, &rc, brush);
     3997    return -1;
     3998}
     3999
     4000
     4001/*********************************************************************
     4002 *
     4003 *  WM_GETTEXT
    39704004 *
    39714005 */
     
    39764010    if(unicode)
    39774011    {
    3978         LPWSTR textW = (LPWSTR)lParam;
    3979         strncpyW(textW, es->text, count);
    3980         textW[count - 1] = 0; /* ensure 0 termination */
    3981         return strlenW(textW);
     4012    LPWSTR textW = (LPWSTR)lParam;
     4013    strncpyW(textW, es->text, count);
     4014    textW[count - 1] = 0; /* ensure 0 termination */
     4015    return strlenW(textW);
    39824016    }
    39834017    else
    39844018    {
    3985         LPSTR textA = (LPSTR)lParam;
    3986         WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, count, NULL, NULL);
    3987         textA[count - 1] = 0; /* ensure 0 termination */
    3988         return strlen(textA);
    3989     }
    3990 }
    3991 
    3992 /*********************************************************************
    3993  *
    3994  *      WM_HSCROLL
     4019    LPSTR textA = (LPSTR)lParam;
     4020    WideCharToMultiByte(CP_ACP, 0, es->text, -1, textA, count, NULL, NULL);
     4021#ifdef __WIN32OS2__
     4022    lstrtrunc( textA, count );
     4023#else
     4024    textA[count - 1] = 0; /* ensure 0 termination */
     4025#endif
     4026    return strlen(textA);
     4027    }
     4028}
     4029
     4030/*********************************************************************
     4031 *
     4032 *  WM_HSCROLL
    39954033 *
    39964034 */
    39974035static LRESULT EDIT_WM_HScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos)
    39984036{
    3999         INT dx;
    4000         INT fw;
    4001 
    4002         if (!(es->style & ES_MULTILINE))
    4003                 return 0;
    4004 
    4005         if (!(es->style & ES_AUTOHSCROLL))
    4006                 return 0;
    4007 
    4008         dx = 0;
    4009         fw = es->format_rect.right - es->format_rect.left;
    4010         switch (action) {
    4011         case SB_LINELEFT:
    4012                 TRACE("SB_LINELEFT\n");
    4013                 if (es->x_offset)
    4014                         dx = -es->char_width;
    4015                 break;
    4016         case SB_LINERIGHT:
    4017                 TRACE("SB_LINERIGHT\n");
    4018                 if (es->x_offset < es->text_width)
    4019                         dx = es->char_width;
    4020                 break;
    4021         case SB_PAGELEFT:
    4022                 TRACE("SB_PAGELEFT\n");
    4023                 if (es->x_offset)
    4024                         dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
    4025                 break;
    4026         case SB_PAGERIGHT:
    4027                 TRACE("SB_PAGERIGHT\n");
    4028                 if (es->x_offset < es->text_width)
    4029                         dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
    4030                 break;
    4031         case SB_LEFT:
    4032                 TRACE("SB_LEFT\n");
    4033                 if (es->x_offset)
    4034                         dx = -es->x_offset;
    4035                 break;
    4036         case SB_RIGHT:
    4037                 TRACE("SB_RIGHT\n");
    4038                 if (es->x_offset < es->text_width)
    4039                         dx = es->text_width - es->x_offset;
    4040                 break;
    4041         case SB_THUMBTRACK:
    4042                 TRACE("SB_THUMBTRACK %d\n", pos);
    4043                 es->flags |= EF_HSCROLL_TRACK;
    4044                 if(es->style & WS_HSCROLL)
    4045                     dx = pos - es->x_offset;
    4046                 else
    4047                 {
    4048                     INT fw, new_x;
    4049                     /* Sanity check */
    4050                     if(pos < 0 || pos > 100) return 0;
    4051                     /* Assume default scroll range 0-100 */
    4052                     fw = es->format_rect.right - es->format_rect.left;
    4053                     new_x = pos * (es->text_width - fw) / 100;
    4054                     dx = es->text_width ? (new_x - es->x_offset) : 0;
    4055                 }
    4056                 break;
    4057         case SB_THUMBPOSITION:
    4058                 TRACE("SB_THUMBPOSITION %d\n", pos);
    4059                 es->flags &= ~EF_HSCROLL_TRACK;
    4060                 if(GetWindowLongA( hwnd, GWL_STYLE ) & WS_HSCROLL)
    4061                     dx = pos - es->x_offset;
    4062                 else
    4063                 {
    4064                     INT fw, new_x;
    4065                     /* Sanity check */
    4066                     if(pos < 0 || pos > 100) return 0;
    4067                     /* Assume default scroll range 0-100 */
    4068                     fw = es->format_rect.right - es->format_rect.left;
    4069                     new_x = pos * (es->text_width - fw) / 100;
    4070                     dx = es->text_width ? (new_x - es->x_offset) : 0;
    4071                 }
    4072                 if (!dx) {
    4073                         /* force scroll info update */
    4074                         EDIT_UpdateScrollInfo(hwnd, es);
    4075                         EDIT_NOTIFY_PARENT(hwnd, es, EN_HSCROLL, "EN_HSCROLL");
    4076                 }
    4077                 break;
    4078         case SB_ENDSCROLL:
    4079                 TRACE("SB_ENDSCROLL\n");
    4080                 break;
    4081         /*
    4082          *      FIXME : the next two are undocumented !
    4083          *      Are we doing the right thing ?
    4084          *      At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
    4085          *      although it's also a regular control message.
    4086         */
    4087         case EM_GETTHUMB: /* this one is used by NT notepad */
    4088         case EM_GETTHUMB16:
    4089         {
    4090                 LRESULT ret;
    4091                 if(GetWindowLongA( hwnd, GWL_STYLE ) & WS_HSCROLL)
    4092                     ret = GetScrollPos(hwnd, SB_HORZ);
    4093                 else
    4094                 {
    4095                     /* Assume default scroll range 0-100 */
    4096                     INT fw = es->format_rect.right - es->format_rect.left;
    4097                     ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0;
    4098                 }
    4099                 TRACE("EM_GETTHUMB: returning %ld\n", ret);
    4100                 return ret;
    4101         }
    4102         case EM_LINESCROLL16:
    4103                 TRACE("EM_LINESCROLL16\n");
    4104                 dx = pos;
    4105                 break;
    4106 
    4107         default:
    4108                 ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n",
     4037    INT dx;
     4038    INT fw;
     4039
     4040    if (!(es->style & ES_MULTILINE))
     4041        return 0;
     4042
     4043    if (!(es->style & ES_AUTOHSCROLL))
     4044        return 0;
     4045
     4046    dx = 0;
     4047    fw = es->format_rect.right - es->format_rect.left;
     4048    switch (action) {
     4049    case SB_LINELEFT:
     4050        TRACE("SB_LINELEFT\n");
     4051        if (es->x_offset)
     4052            dx = -es->char_width;
     4053        break;
     4054    case SB_LINERIGHT:
     4055        TRACE("SB_LINERIGHT\n");
     4056        if (es->x_offset < es->text_width)
     4057            dx = es->char_width;
     4058        break;
     4059    case SB_PAGELEFT:
     4060        TRACE("SB_PAGELEFT\n");
     4061        if (es->x_offset)
     4062            dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
     4063        break;
     4064    case SB_PAGERIGHT:
     4065        TRACE("SB_PAGERIGHT\n");
     4066        if (es->x_offset < es->text_width)
     4067            dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
     4068        break;
     4069    case SB_LEFT:
     4070        TRACE("SB_LEFT\n");
     4071        if (es->x_offset)
     4072            dx = -es->x_offset;
     4073        break;
     4074    case SB_RIGHT:
     4075        TRACE("SB_RIGHT\n");
     4076        if (es->x_offset < es->text_width)
     4077            dx = es->text_width - es->x_offset;
     4078        break;
     4079    case SB_THUMBTRACK:
     4080        TRACE("SB_THUMBTRACK %d\n", pos);
     4081        es->flags |= EF_HSCROLL_TRACK;
     4082        if(es->style & WS_HSCROLL)
     4083            dx = pos - es->x_offset;
     4084        else
     4085        {
     4086            INT fw, new_x;
     4087            /* Sanity check */
     4088            if(pos < 0 || pos > 100) return 0;
     4089            /* Assume default scroll range 0-100 */
     4090            fw = es->format_rect.right - es->format_rect.left;
     4091            new_x = pos * (es->text_width - fw) / 100;
     4092            dx = es->text_width ? (new_x - es->x_offset) : 0;
     4093        }
     4094        break;
     4095    case SB_THUMBPOSITION:
     4096        TRACE("SB_THUMBPOSITION %d\n", pos);
     4097        es->flags &= ~EF_HSCROLL_TRACK;
     4098        if(GetWindowLongA( hwnd, GWL_STYLE ) & WS_HSCROLL)
     4099            dx = pos - es->x_offset;
     4100        else
     4101        {
     4102            INT fw, new_x;
     4103            /* Sanity check */
     4104            if(pos < 0 || pos > 100) return 0;
     4105            /* Assume default scroll range 0-100 */
     4106            fw = es->format_rect.right - es->format_rect.left;
     4107            new_x = pos * (es->text_width - fw) / 100;
     4108            dx = es->text_width ? (new_x - es->x_offset) : 0;
     4109        }
     4110        if (!dx) {
     4111            /* force scroll info update */
     4112            EDIT_UpdateScrollInfo(hwnd, es);
     4113            EDIT_NOTIFY_PARENT(hwnd, es, EN_HSCROLL, "EN_HSCROLL");
     4114        }
     4115        break;
     4116    case SB_ENDSCROLL:
     4117        TRACE("SB_ENDSCROLL\n");
     4118        break;
     4119    /*
     4120     *  FIXME : the next two are undocumented !
     4121     *  Are we doing the right thing ?
     4122     *  At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
     4123     *  although it's also a regular control message.
     4124    */
     4125    case EM_GETTHUMB: /* this one is used by NT notepad */
     4126    case EM_GETTHUMB16:
     4127    {
     4128        LRESULT ret;
     4129        if(GetWindowLongA( hwnd, GWL_STYLE ) & WS_HSCROLL)
     4130            ret = GetScrollPos(hwnd, SB_HORZ);
     4131        else
     4132        {
     4133            /* Assume default scroll range 0-100 */
     4134            INT fw = es->format_rect.right - es->format_rect.left;
     4135            ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0;
     4136        }
     4137        TRACE("EM_GETTHUMB: returning %ld\n", ret);
     4138        return ret;
     4139    }
     4140    case EM_LINESCROLL16:
     4141        TRACE("EM_LINESCROLL16\n");
     4142        dx = pos;
     4143        break;
     4144
     4145    default:
     4146        ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n",
    41094147                    action, action);
    4110                 return 0;
    4111         }
    4112         if (dx)
    4113         {
    4114             INT fw = es->format_rect.right - es->format_rect.left;
    4115             /* check if we are going to move too far */
    4116             if(es->x_offset + dx + fw > es->text_width)
    4117                 dx = es->text_width - fw - es->x_offset;
    4118             if(dx)
    4119                 EDIT_EM_LineScroll_internal(hwnd, es, dx, 0);
    4120         }
    4121         return 0;
    4122 }
    4123 
    4124 
    4125 /*********************************************************************
    4126  *
    4127  *      EDIT_CheckCombo
     4148        return 0;
     4149    }
     4150    if (dx)
     4151    {
     4152        INT fw = es->format_rect.right - es->format_rect.left;
     4153        /* check if we are going to move too far */
     4154        if(es->x_offset + dx + fw > es->text_width)
     4155        dx = es->text_width - fw - es->x_offset;
     4156        if(dx)
     4157        EDIT_EM_LineScroll_internal(hwnd, es, dx, 0);
     4158    }
     4159    return 0;
     4160}
     4161
     4162
     4163/*********************************************************************
     4164 *
     4165 *  EDIT_CheckCombo
    41284166 *
    41294167 */
     
    41434181
    41444182   TRACE_(combo)("[%04x]: handling msg %04x (%04x)\n",
    4145                      hwnd, (UINT16)msg, (UINT16)key);
     4183                 hwnd, (UINT16)msg, (UINT16)key);
    41464184
    41474185   if (key == VK_UP || key == VK_DOWN)
     
    41854223/*********************************************************************
    41864224 *
    4187  *      WM_KEYDOWN
    4188  *
    4189  *      Handling of special keys that don't produce a WM_CHAR
    4190  *      (i.e. non-printable keys) & Backspace & Delete
     4225 *  WM_KEYDOWN
     4226 *
     4227 *  Handling of special keys that don't produce a WM_CHAR
     4228 *  (i.e. non-printable keys) & Backspace & Delete
    41914229 *
    41924230 */
    41934231static LRESULT EDIT_WM_KeyDown(HWND hwnd, EDITSTATE *es, INT key)
    41944232{
    4195         BOOL shift;
    4196         BOOL control;
    4197 
    4198         if (GetKeyState(VK_MENU) & 0x8000)
    4199                 return 0;
    4200 
    4201         shift = GetKeyState(VK_SHIFT) & 0x8000;
    4202         control = GetKeyState(VK_CONTROL) & 0x8000;
    4203 
    4204         switch (key) {
    4205         case VK_F4:
    4206         case VK_UP:
    4207                 if (EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key) || key == VK_F4)
    4208                         break;
    4209 
    4210                 /* fall through */
    4211         case VK_LEFT:
    4212                 if ((es->style & ES_MULTILINE) && (key == VK_UP))
    4213                         EDIT_MoveUp_ML(hwnd, es, shift);
    4214                 else
    4215                         if (control)
    4216                                 EDIT_MoveWordBackward(hwnd, es, shift);
    4217                         else
    4218                                 EDIT_MoveBackward(hwnd, es, shift);
    4219                 break;
    4220         case VK_DOWN:
    4221                 if (EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key))
    4222                         break;
    4223                 /* fall through */
    4224         case VK_RIGHT:
    4225                 if ((es->style & ES_MULTILINE) && (key == VK_DOWN))
    4226                         EDIT_MoveDown_ML(hwnd, es, shift);
    4227                 else if (control)
    4228                         EDIT_MoveWordForward(hwnd, es, shift);
    4229                 else
    4230                         EDIT_MoveForward(hwnd, es, shift);
    4231                 break;
    4232         case VK_HOME:
    4233                 EDIT_MoveHome(hwnd, es, shift);
    4234                 break;
    4235         case VK_END:
    4236                 EDIT_MoveEnd(hwnd, es, shift);
    4237                 break;
    4238         case VK_PRIOR:
    4239                 if (es->style & ES_MULTILINE)
    4240                         EDIT_MovePageUp_ML(hwnd, es, shift);
    4241                 else
    4242                         EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key);
    4243                 break;
    4244         case VK_NEXT:
    4245                 if (es->style & ES_MULTILINE)
    4246                         EDIT_MovePageDown_ML(hwnd, es, shift);
    4247                 else
    4248                         EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key);
    4249                 break;
    4250         case VK_DELETE:
    4251                 if (!(es->style & ES_READONLY) && !(shift && control)) {
    4252                         if (es->selection_start != es->selection_end) {
    4253                                 if (shift)
    4254                                         EDIT_WM_Cut(hwnd, es);
    4255                                 else
    4256                                         EDIT_WM_Clear(hwnd, es);
    4257                         } else {
    4258                                 if (shift) {
    4259                                         /* delete character left of caret */
    4260                                         EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
    4261                                         EDIT_MoveBackward(hwnd, es, TRUE);
    4262                                         EDIT_WM_Clear(hwnd, es);
    4263                                 } else if (control) {
    4264                                         /* delete to end of line */
    4265                                         EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
    4266                                         EDIT_MoveEnd(hwnd, es, TRUE);
    4267                                         EDIT_WM_Clear(hwnd, es);
    4268                                 } else {
    4269                                         /* delete character right of caret */
    4270                                         EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
    4271                                         EDIT_MoveForward(hwnd, es, TRUE);
    4272                                         EDIT_WM_Clear(hwnd, es);
    4273                                 }
    4274                         }
    4275                 }
    4276                 break;
    4277         case VK_INSERT:
    4278                 if (shift) {
    4279                         if (!(es->style & ES_READONLY))
    4280                                 EDIT_WM_Paste(hwnd, es);
    4281                 } else if (control)
    4282                         EDIT_WM_Copy(hwnd, es);
    4283                 break;
    4284         case VK_RETURN:
    4285             /* If the edit doesn't want the return send a message to the default object */
    4286             if(!(es->style & ES_WANTRETURN))
    4287             {
    4288                 HWND hwndParent = GetParent(hwnd);
    4289                 DWORD dw = SendMessageW( hwndParent, DM_GETDEFID, 0, 0 );
    4290                 if (HIWORD(dw) == DC_HASDEFID)
    4291                 {
    4292                     SendMessageW( hwndParent, WM_COMMAND,
    4293                                   MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
    4294                               (LPARAM)GetDlgItem( hwndParent, LOWORD(dw) ) );
    4295                 }
    4296             }
    4297             break;
    4298         }
    4299         return 0;
    4300 }
    4301 
    4302 
    4303 /*********************************************************************
    4304  *
    4305  *      WM_KILLFOCUS
     4233    BOOL shift;
     4234    BOOL control;
     4235
     4236    if (GetKeyState(VK_MENU) & 0x8000)
     4237        return 0;
     4238
     4239    shift = GetKeyState(VK_SHIFT) & 0x8000;
     4240    control = GetKeyState(VK_CONTROL) & 0x8000;
     4241
     4242    switch (key) {
     4243    case VK_F4:
     4244    case VK_UP:
     4245        if (EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key) || key == VK_F4)
     4246            break;
     4247
     4248        /* fall through */
     4249    case VK_LEFT:
     4250        if ((es->style & ES_MULTILINE) && (key == VK_UP))
     4251            EDIT_MoveUp_ML(hwnd, es, shift);
     4252        else
     4253            if (control)
     4254                EDIT_MoveWordBackward(hwnd, es, shift);
     4255            else
     4256                EDIT_MoveBackward(hwnd, es, shift);
     4257        break;
     4258    case VK_DOWN:
     4259        if (EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key))
     4260            break;
     4261        /* fall through */
     4262    case VK_RIGHT:
     4263        if ((es->style & ES_MULTILINE) && (key == VK_DOWN))
     4264            EDIT_MoveDown_ML(hwnd, es, shift);
     4265        else if (control)
     4266            EDIT_MoveWordForward(hwnd, es, shift);
     4267        else
     4268            EDIT_MoveForward(hwnd, es, shift);
     4269        break;
     4270    case VK_HOME:
     4271        EDIT_MoveHome(hwnd, es, shift);
     4272        break;
     4273    case VK_END:
     4274        EDIT_MoveEnd(hwnd, es, shift);
     4275        break;
     4276    case VK_PRIOR:
     4277        if (es->style & ES_MULTILINE)
     4278            EDIT_MovePageUp_ML(hwnd, es, shift);
     4279        else
     4280            EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key);
     4281        break;
     4282    case VK_NEXT:
     4283        if (es->style & ES_MULTILINE)
     4284            EDIT_MovePageDown_ML(hwnd, es, shift);
     4285        else
     4286            EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key);
     4287        break;
     4288    case VK_DELETE:
     4289        if (!(es->style & ES_READONLY) && !(shift && control)) {
     4290            if (es->selection_start != es->selection_end) {
     4291                if (shift)
     4292                    EDIT_WM_Cut(hwnd, es);
     4293                else
     4294                    EDIT_WM_Clear(hwnd, es);
     4295            } else {
     4296                if (shift) {
     4297                    /* delete character left of caret */
     4298                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     4299                    EDIT_MoveBackward(hwnd, es, TRUE);
     4300                    EDIT_WM_Clear(hwnd, es);
     4301                } else if (control) {
     4302                    /* delete to end of line */
     4303                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     4304                    EDIT_MoveEnd(hwnd, es, TRUE);
     4305                    EDIT_WM_Clear(hwnd, es);
     4306                } else {
     4307                    /* delete character right of caret */
     4308                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     4309                    EDIT_MoveForward(hwnd, es, TRUE);
     4310                    EDIT_WM_Clear(hwnd, es);
     4311                }
     4312            }
     4313        }
     4314        break;
     4315    case VK_INSERT:
     4316        if (shift) {
     4317            if (!(es->style & ES_READONLY))
     4318                EDIT_WM_Paste(hwnd, es);
     4319        } else if (control)
     4320            EDIT_WM_Copy(hwnd, es);
     4321        break;
     4322    case VK_RETURN:
     4323        /* If the edit doesn't want the return send a message to the default object */
     4324        if(!(es->style & ES_WANTRETURN))
     4325        {
     4326        HWND hwndParent = GetParent(hwnd);
     4327        DWORD dw = SendMessageW( hwndParent, DM_GETDEFID, 0, 0 );
     4328        if (HIWORD(dw) == DC_HASDEFID)
     4329        {
     4330            SendMessageW( hwndParent, WM_COMMAND,
     4331                  MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
     4332                  (LPARAM)GetDlgItem( hwndParent, LOWORD(dw) ) );
     4333        }
     4334        }
     4335        break;
     4336    }
     4337    return 0;
     4338}
     4339
     4340
     4341/*********************************************************************
     4342 *
     4343 *  WM_KILLFOCUS
    43064344 *
    43074345 */
    43084346static LRESULT EDIT_WM_KillFocus(HWND hwnd, EDITSTATE *es)
    43094347{
    4310         es->flags &= ~EF_FOCUSED;
    4311         DestroyCaret();
    4312         if(!(es->style & ES_NOHIDESEL))
    4313                 EDIT_InvalidateText(hwnd, es, es->selection_start, es->selection_end);
    4314         EDIT_NOTIFY_PARENT(hwnd, es, EN_KILLFOCUS, "EN_KILLFOCUS");
    4315         return 0;
    4316 }
    4317 
    4318 
    4319 /*********************************************************************
    4320  *
    4321  *      WM_LBUTTONDBLCLK
    4322  *
    4323  *      The caret position has been set on the WM_LBUTTONDOWN message
     4348    es->flags &= ~EF_FOCUSED;
     4349    DestroyCaret();
     4350    if(!(es->style & ES_NOHIDESEL))
     4351        EDIT_InvalidateText(hwnd, es, es->selection_start, es->selection_end);
     4352    EDIT_NOTIFY_PARENT(hwnd, es, EN_KILLFOCUS, "EN_KILLFOCUS");
     4353    return 0;
     4354}
     4355
     4356
     4357/*********************************************************************
     4358 *
     4359 *  WM_LBUTTONDBLCLK
     4360 *
     4361 *  The caret position has been set on the WM_LBUTTONDOWN message
    43244362 *
    43254363 */
    43264364static LRESULT EDIT_WM_LButtonDblClk(HWND hwnd, EDITSTATE *es)
    43274365{
    4328         INT s;
    4329         INT e = es->selection_end;
    4330         INT l;
    4331         INT li;
    4332         INT ll;
    4333 
    4334         if (!(es->flags & EF_FOCUSED))
    4335                 return 0;
    4336 
    4337         l = EDIT_EM_LineFromChar(es, e);
    4338         li = EDIT_EM_LineIndex(es, l);
    4339         ll = EDIT_EM_LineLength(es, e);
    4340         s = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_LEFT);
    4341         e = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_RIGHT);
    4342         EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
    4343         EDIT_EM_ScrollCaret(hwnd, es);
    4344         return 0;
    4345 }
    4346 
    4347 
    4348 /*********************************************************************
    4349  *
    4350  *      WM_LBUTTONDOWN
     4366    INT s;
     4367    INT e = es->selection_end;
     4368    INT l;
     4369    INT li;
     4370    INT ll;
     4371
     4372    if (!(es->flags & EF_FOCUSED))
     4373        return 0;
     4374
     4375    l = EDIT_EM_LineFromChar(es, e);
     4376    li = EDIT_EM_LineIndex(es, l);
     4377    ll = EDIT_EM_LineLength(es, e);
     4378    s = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_LEFT);
     4379    e = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_RIGHT);
     4380    EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
     4381    EDIT_EM_ScrollCaret(hwnd, es);
     4382    return 0;
     4383}
     4384
     4385
     4386/*********************************************************************
     4387 *
     4388 *  WM_LBUTTONDOWN
    43514389 *
    43524390 */
    43534391static LRESULT EDIT_WM_LButtonDown(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y)
    43544392{
    4355         INT e;
    4356         BOOL after_wrap;
    4357 
    4358         if (!(es->flags & EF_FOCUSED))
    4359                 return 0;
    4360 
    4361         es->bCaptureState = TRUE;
    4362         SetCapture(hwnd);
    4363         EDIT_ConfinePoint(es, &x, &y);
    4364         e = EDIT_CharFromPos(hwnd, es, x, y, &after_wrap);
    4365         EDIT_EM_SetSel(hwnd, es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
    4366         EDIT_EM_ScrollCaret(hwnd, es);
    4367         es->region_posx = es->region_posy = 0;
    4368         SetTimer(hwnd, 0, 100, NULL);
    4369         return 0;
    4370 }
    4371 
    4372 
    4373 /*********************************************************************
    4374  *
    4375  *      WM_LBUTTONUP
     4393    INT e;
     4394    BOOL after_wrap;
     4395
     4396    if (!(es->flags & EF_FOCUSED))
     4397        return 0;
     4398
     4399    es->bCaptureState = TRUE;
     4400    SetCapture(hwnd);
     4401    EDIT_ConfinePoint(es, &x, &y);
     4402    e = EDIT_CharFromPos(hwnd, es, x, y, &after_wrap);
     4403    EDIT_EM_SetSel(hwnd, es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
     4404    EDIT_EM_ScrollCaret(hwnd, es);
     4405    es->region_posx = es->region_posy = 0;
     4406    SetTimer(hwnd, 0, 100, NULL);
     4407    return 0;
     4408}
     4409
     4410
     4411/*********************************************************************
     4412 *
     4413 *  WM_LBUTTONUP
    43764414 *
    43774415 */
     
    43794417{
    43804418#ifdef __WIN32OS2__
    4381         if (es->bCaptureState) {
    4382                 KillTimer(hwndSelf, 0);
    4383                 if(GetCapture() == hwndSelf) ReleaseCapture();
    4384         }
     4419    if (es->bCaptureState) {
     4420        KillTimer(hwndSelf, 0);
     4421        if(GetCapture() == hwndSelf) ReleaseCapture();
     4422    }
    43854423#else
    4386         if (es->bCaptureState && GetCapture() == hwndSelf) {
    4387                 KillTimer(hwndSelf, 0);
    4388                 ReleaseCapture();
    4389         }
     4424    if (es->bCaptureState && GetCapture() == hwndSelf) {
     4425        KillTimer(hwndSelf, 0);
     4426        ReleaseCapture();
     4427    }
    43904428#endif
    4391         es->bCaptureState = FALSE;
    4392         return 0;
    4393 }
    4394 
    4395 
    4396 /*********************************************************************
    4397  *
    4398  *      WM_MBUTTONDOWN
     4429    es->bCaptureState = FALSE;
     4430    return 0;
     4431}
     4432
     4433
     4434/*********************************************************************
     4435 *
     4436 *  WM_MBUTTONDOWN
    43994437 *
    44004438 */
     
    44084446/*********************************************************************
    44094447 *
    4410  *      WM_MOUSEMOVE
     4448 *  WM_MOUSEMOVE
    44114449 *
    44124450 */
    44134451static LRESULT EDIT_WM_MouseMove(HWND hwnd, EDITSTATE *es, INT x, INT y)
    44144452{
    4415         INT e;
    4416         BOOL after_wrap;
    4417         INT prex, prey;
    4418 
    4419         if (GetCapture() != hwnd)
    4420                 return 0;
    4421 
    4422         /*
    4423          *      FIXME: gotta do some scrolling if outside client
    4424          *              area.  Maybe reset the timer ?
    4425         */
    4426         prex = x; prey = y;
    4427         EDIT_ConfinePoint(es, &x, &y);
    4428         es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
    4429         es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
    4430         e = EDIT_CharFromPos(hwnd, es, x, y, &after_wrap);
    4431         EDIT_EM_SetSel(hwnd, es, es->selection_start, e, after_wrap);
    4432         return 0;
    4433 }
    4434 
    4435 
    4436 /*********************************************************************
    4437  *
    4438  *      WM_NCCREATE
     4453    INT e;
     4454    BOOL after_wrap;
     4455    INT prex, prey;
     4456
     4457    if (GetCapture() != hwnd)
     4458        return 0;
     4459
     4460    /*
     4461     *  FIXME: gotta do some scrolling if outside client
     4462     *      area.  Maybe reset the timer ?
     4463    */
     4464    prex = x; prey = y;
     4465    EDIT_ConfinePoint(es, &x, &y);
     4466    es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
     4467    es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
     4468    e = EDIT_CharFromPos(hwnd, es, x, y, &after_wrap);
     4469    EDIT_EM_SetSel(hwnd, es, es->selection_start, e, after_wrap);
     4470    return 0;
     4471}
     4472
     4473
     4474/*********************************************************************
     4475 *
     4476 *  WM_NCCREATE
    44394477 *
    44404478 * See also EDIT_WM_StyleChanged
     
    44424480static LRESULT EDIT_WM_NCCreate(HWND hwnd, DWORD style, HWND hwndParent, BOOL unicode)
    44434481{
    4444         EDITSTATE *es;
    4445         UINT alloc_size;
    4446 
    4447         TRACE("Creating %s edit control, style = %08lx\n",
    4448                 unicode ? "Unicode" : "ANSI", style);
    4449 
    4450         if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
    4451                 return FALSE;
     4482    EDITSTATE *es;
     4483    UINT alloc_size;
     4484
     4485    TRACE("Creating %s edit control, style = %08lx\n",
     4486        unicode ? "Unicode" : "ANSI", style);
     4487
     4488    if (!(es = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
     4489        return FALSE;
    44524490        SetWindowLongA( hwnd, 0, (LONG)es );
    44534491
     
    44584496        */
    44594497
    4460         es->is_unicode = unicode;
    4461         es->style = style;
     4498    es->is_unicode = unicode;
     4499    es->style = style;
    44624500
    44634501        es->bEnableState = !(style & WS_DISABLED);
    44644502
    4465         /* Save parent, which will be notified by EN_* messages */
    4466         es->hwndParent = hwndParent;
    4467 
    4468         if (es->style & ES_COMBO)
    4469            es->hwndListBox = GetDlgItem(hwndParent, ID_CB_LISTBOX);
     4503    /* Save parent, which will be notified by EN_* messages */
     4504    es->hwndParent = hwndParent;
     4505
     4506    if (es->style & ES_COMBO)
     4507       es->hwndListBox = GetDlgItem(hwndParent, ID_CB_LISTBOX);
    44704508
    44714509        /* Number overrides lowercase overrides uppercase (at least it
     
    44784516                es->style &= ~ES_UPPERCASE;
    44794517        }
    4480         if (es->style & ES_MULTILINE) {
    4481                 es->buffer_limit = BUFLIMIT_MULTI;
    4482                 if (es->style & WS_VSCROLL)
    4483                         es->style |= ES_AUTOVSCROLL;
    4484                 if (es->style & WS_HSCROLL)
    4485                         es->style |= ES_AUTOHSCROLL;
    4486                 es->style &= ~ES_PASSWORD;
    4487                 if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
     4518    if (es->style & ES_MULTILINE) {
     4519        es->buffer_limit = BUFLIMIT_MULTI;
     4520        if (es->style & WS_VSCROLL)
     4521            es->style |= ES_AUTOVSCROLL;
     4522        if (es->style & WS_HSCROLL)
     4523            es->style |= ES_AUTOHSCROLL;
     4524        es->style &= ~ES_PASSWORD;
     4525        if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
    44884526                        /* Confirmed - RIGHT overrides CENTER */
    4489                         if (es->style & ES_RIGHT)
    4490                                 es->style &= ~ES_CENTER;
    4491                         es->style &= ~WS_HSCROLL;
    4492                         es->style &= ~ES_AUTOHSCROLL;
    4493                 }
    4494 
    4495                 /* FIXME: for now, all multi line controls are AUTOVSCROLL */
    4496                 es->style |= ES_AUTOVSCROLL;
    4497         } else {
    4498                 es->buffer_limit = BUFLIMIT_SINGLE;
     4527            if (es->style & ES_RIGHT)
     4528                es->style &= ~ES_CENTER;
     4529            es->style &= ~WS_HSCROLL;
     4530            es->style &= ~ES_AUTOHSCROLL;
     4531        }
     4532
     4533        /* FIXME: for now, all multi line controls are AUTOVSCROLL */
     4534        es->style |= ES_AUTOVSCROLL;
     4535    } else {
     4536        es->buffer_limit = BUFLIMIT_SINGLE;
    44994537                if (WIN31_LOOK == TWEAK_WineLook ||
    45004538                    WIN95_LOOK == TWEAK_WineLook) {
    4501                         es->style &= ~ES_CENTER;
    4502                         es->style &= ~ES_RIGHT;
     4539                es->style &= ~ES_CENTER;
     4540                es->style &= ~ES_RIGHT;
    45034541                } else {
    4504                         if (es->style & ES_RIGHT)
    4505                                 es->style &= ~ES_CENTER;
     4542            if (es->style & ES_RIGHT)
     4543                es->style &= ~ES_CENTER;
    45064544                }
    4507                 es->style &= ~WS_HSCROLL;
    4508                 es->style &= ~WS_VSCROLL;
    4509                 es->style &= ~ES_AUTOVSCROLL;
    4510                 es->style &= ~ES_WANTRETURN;
    4511                 if (es->style & ES_PASSWORD)
    4512                         es->password_char = '*';
    4513 
    4514                 /* FIXME: for now, all single line controls are AUTOHSCROLL */
    4515                 es->style |= ES_AUTOHSCROLL;
    4516         }
    4517 
    4518         alloc_size = ROUND_TO_GROW((es->buffer_size + 1) * sizeof(WCHAR));
    4519         if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
    4520             return FALSE;
    4521         es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
    4522 
    4523         if (!(es->undo_text = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (es->buffer_size + 1) * sizeof(WCHAR))))
    4524                 return FALSE;
    4525         es->undo_buffer_size = es->buffer_size;
    4526 
    4527         if (es->style & ES_MULTILINE)
    4528                 if (!(es->first_line_def = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
    4529                         return FALSE;
    4530         es->line_count = 1;
    4531 
    4532         /*
    4533         * In Win95 look and feel, the WS_BORDER style is replaced by the
    4534         * WS_EX_CLIENTEDGE style for the edit control. This gives the edit
    4535         * control a non client area.  Not always.  This coordinates in some
     4545        es->style &= ~WS_HSCROLL;
     4546        es->style &= ~WS_VSCROLL;
     4547        es->style &= ~ES_AUTOVSCROLL;
     4548        es->style &= ~ES_WANTRETURN;
     4549        if (es->style & ES_PASSWORD)
     4550            es->password_char = '*';
     4551
     4552        /* FIXME: for now, all single line controls are AUTOHSCROLL */
     4553        es->style |= ES_AUTOHSCROLL;
     4554    }
     4555
     4556    alloc_size = ROUND_TO_GROW((es->buffer_size + 1) * sizeof(WCHAR));
     4557    if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
     4558        return FALSE;
     4559    es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
     4560
     4561    if (!(es->undo_text = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (es->buffer_size + 1) * sizeof(WCHAR))))
     4562        return FALSE;
     4563    es->undo_buffer_size = es->buffer_size;
     4564
     4565    if (es->style & ES_MULTILINE)
     4566        if (!(es->first_line_def = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
     4567            return FALSE;
     4568    es->line_count = 1;
     4569
     4570    /*
     4571    * In Win95 look and feel, the WS_BORDER style is replaced by the
     4572    * WS_EX_CLIENTEDGE style for the edit control. This gives the edit
     4573    * control a non client area.  Not always.  This coordinates in some
    45364574         * way with the window creation code in dialog.c  When making
    45374575         * modifications please ensure that the code still works for edit
    45384576         * controls created directly with style 0x50800000, exStyle 0 (
    45394577         * which should have a single pixel border)
    4540         */
    4541         if (TWEAK_WineLook != WIN31_LOOK)
    4542         {
    4543           es->style      &= ~WS_BORDER;
    4544         }
    4545         else
    4546         {
    4547           if ((es->style & WS_BORDER) && !(es->style & WS_DLGFRAME))
     4578    */
     4579    if (TWEAK_WineLook != WIN31_LOOK)
     4580    {
     4581      es->style      &= ~WS_BORDER;
     4582    }
     4583    else
     4584    {
     4585      if ((es->style & WS_BORDER) && !(es->style & WS_DLGFRAME))
    45484586              SetWindowLongA( hwnd, GWL_STYLE,
    45494587                              GetWindowLongA( hwnd, GWL_STYLE ) & ~WS_BORDER );
    4550         }
    4551 
    4552         return TRUE;
    4553 }
    4554 
    4555 /*********************************************************************
    4556  *
    4557  *      WM_PAINT
     4588    }
     4589
     4590    return TRUE;
     4591}
     4592
     4593/*********************************************************************
     4594 *
     4595 *  WM_PAINT
    45584596 *
    45594597 */
    45604598static void EDIT_WM_Paint(HWND hwnd, EDITSTATE *es, WPARAM wParam)
    45614599{
    4562         PAINTSTRUCT ps;
    4563         INT i;
    4564         HDC dc;
    4565         HFONT old_font = 0;
    4566         RECT rc;
    4567         RECT rcLine;
    4568         RECT rcRgn;
    4569         BOOL rev = es->bEnableState &&
    4570                                 ((es->flags & EF_FOCUSED) ||
    4571                                         (es->style & ES_NOHIDESEL));
     4600    PAINTSTRUCT ps;
     4601    INT i;
     4602    HDC dc;
     4603    HFONT old_font = 0;
     4604    RECT rc;
     4605    RECT rcLine;
     4606    RECT rcRgn;
     4607    BOOL rev = es->bEnableState &&
     4608                ((es->flags & EF_FOCUSED) ||
     4609                    (es->style & ES_NOHIDESEL));
    45724610        if (!wParam)
    45734611            dc = BeginPaint(hwnd, &ps);
    45744612        else
    45754613            dc = (HDC) wParam;
    4576         if(es->style & WS_BORDER) {
    4577                 GetClientRect(hwnd, &rc);
    4578                 if(es->style & ES_MULTILINE) {
    4579                         if(es->style & WS_HSCROLL) rc.bottom++;
    4580                         if(es->style & WS_VSCROLL) rc.right++;
    4581                 }
    4582                 Rectangle(dc, rc.left, rc.top, rc.right, rc.bottom);
    4583         }
    4584         IntersectClipRect(dc, es->format_rect.left,
    4585                                 es->format_rect.top,
    4586                                 es->format_rect.right,
    4587                                 es->format_rect.bottom);
    4588         if (es->style & ES_MULTILINE) {
    4589                 GetClientRect(hwnd, &rc);
    4590                 IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
    4591         }
    4592         if (es->font)
    4593                 old_font = SelectObject(dc, es->font);
     4614    if(es->style & WS_BORDER) {
     4615        GetClientRect(hwnd, &rc);
     4616        if(es->style & ES_MULTILINE) {
     4617            if(es->style & WS_HSCROLL) rc.bottom++;
     4618            if(es->style & WS_VSCROLL) rc.right++;
     4619        }
     4620        Rectangle(dc, rc.left, rc.top, rc.right, rc.bottom);
     4621    }
     4622    IntersectClipRect(dc, es->format_rect.left,
     4623                es->format_rect.top,
     4624                es->format_rect.right,
     4625                es->format_rect.bottom);
     4626    if (es->style & ES_MULTILINE) {
     4627        GetClientRect(hwnd, &rc);
     4628        IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
     4629    }
     4630    if (es->font)
     4631        old_font = SelectObject(dc, es->font);
    45944632        if ( get_app_version() >= 0x40000 &&(
    45954633                    !es->bEnableState || (es->style & ES_READONLY)))
     
    45984636                EDIT_SEND_CTLCOLOR(hwnd, dc);
    45994637
    4600         if (!es->bEnableState)
    4601                 SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT));
    4602         GetClipBox(dc, &rcRgn);
    4603         if (es->style & ES_MULTILINE) {
    4604                 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    4605                 for (i = es->y_offset ; i <= min(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++) {
    4606                         EDIT_GetLineRect(hwnd, es, i, 0, -1, &rcLine);
    4607                         if (IntersectRect(&rc, &rcRgn, &rcLine))
    4608                                 EDIT_PaintLine(hwnd, es, dc, i, rev);
    4609                 }
    4610         } else {
    4611                 EDIT_GetLineRect(hwnd, es, 0, 0, -1, &rcLine);
    4612                 if (IntersectRect(&rc, &rcRgn, &rcLine))
    4613                         EDIT_PaintLine(hwnd, es, dc, 0, rev);
    4614         }
    4615         if (es->font)
    4616                 SelectObject(dc, old_font);
     4638    if (!es->bEnableState)
     4639        SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT));
     4640    GetClipBox(dc, &rcRgn);
     4641    if (es->style & ES_MULTILINE) {
     4642        INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     4643        for (i = es->y_offset ; i <= min(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++) {
     4644            EDIT_GetLineRect(hwnd, es, i, 0, -1, &rcLine);
     4645            if (IntersectRect(&rc, &rcRgn, &rcLine))
     4646                EDIT_PaintLine(hwnd, es, dc, i, rev);
     4647        }
     4648    } else {
     4649        EDIT_GetLineRect(hwnd, es, 0, 0, -1, &rcLine);
     4650        if (IntersectRect(&rc, &rcRgn, &rcLine))
     4651            EDIT_PaintLine(hwnd, es, dc, 0, rev);
     4652    }
     4653    if (es->font)
     4654        SelectObject(dc, old_font);
    46174655
    46184656        if (!wParam)
     
    46234661/*********************************************************************
    46244662 *
    4625  *      WM_PASTE
     4663 *  WM_PASTE
    46264664 *
    46274665 */
    46284666static void EDIT_WM_Paste(HWND hwnd, EDITSTATE *es)
    46294667{
    4630         HGLOBAL hsrc;
    4631         LPWSTR src;
    4632 
    4633         /* Protect read-only edit control from modification */
    4634         if(es->style & ES_READONLY)
    4635             return;
    4636 
    4637         OpenClipboard(hwnd);
    4638         if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
    4639                 src = (LPWSTR)GlobalLock(hsrc);
    4640                 EDIT_EM_ReplaceSel(hwnd, es, TRUE, src, TRUE);
    4641                 GlobalUnlock(hsrc);
    4642         }
    4643         CloseClipboard();
    4644 }
    4645 
    4646 
    4647 /*********************************************************************
    4648  *
    4649  *      WM_SETFOCUS
     4668    HGLOBAL hsrc;
     4669    LPWSTR src;
     4670
     4671    /* Protect read-only edit control from modification */
     4672    if(es->style & ES_READONLY)
     4673        return;
     4674
     4675    OpenClipboard(hwnd);
     4676    if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
     4677        src = (LPWSTR)GlobalLock(hsrc);
     4678        EDIT_EM_ReplaceSel(hwnd, es, TRUE, src, TRUE);
     4679        GlobalUnlock(hsrc);
     4680    }
     4681    CloseClipboard();
     4682}
     4683
     4684
     4685/*********************************************************************
     4686 *
     4687 *  WM_SETFOCUS
    46504688 *
    46514689 */
    46524690static void EDIT_WM_SetFocus(HWND hwnd, EDITSTATE *es)
    46534691{
    4654         es->flags |= EF_FOCUSED;
    4655         CreateCaret(hwnd, 0, 2, es->line_height);
    4656         EDIT_SetCaretPos(hwnd, es, es->selection_end,
    4657                         es->flags & EF_AFTER_WRAP);
    4658         if(!(es->style & ES_NOHIDESEL))
    4659                 EDIT_InvalidateText(hwnd, es, es->selection_start, es->selection_end);
    4660         ShowCaret(hwnd);
    4661         EDIT_NOTIFY_PARENT(hwnd, es, EN_SETFOCUS, "EN_SETFOCUS");
    4662 }
    4663 
    4664 
    4665 /*********************************************************************
    4666  *
    4667  *      WM_SETFONT
     4692    es->flags |= EF_FOCUSED;
     4693    CreateCaret(hwnd, 0, 2, es->line_height);
     4694    EDIT_SetCaretPos(hwnd, es, es->selection_end,
     4695            es->flags & EF_AFTER_WRAP);
     4696    if(!(es->style & ES_NOHIDESEL))
     4697        EDIT_InvalidateText(hwnd, es, es->selection_start, es->selection_end);
     4698    ShowCaret(hwnd);
     4699    EDIT_NOTIFY_PARENT(hwnd, es, EN_SETFOCUS, "EN_SETFOCUS");
     4700}
     4701
     4702
     4703/*********************************************************************
     4704 *
     4705 *  WM_SETFONT
    46684706 *
    46694707 * With Win95 look the margins are set to default font value unless
     
    46744712static void EDIT_WM_SetFont(HWND hwnd, EDITSTATE *es, HFONT font, BOOL redraw)
    46754713{
    4676         TEXTMETRICW tm;
    4677         HDC dc;
    4678         HFONT old_font = 0;
    4679         RECT r;
    4680 
    4681         es->font = font;
    4682         dc = GetDC(hwnd);
    4683         if (font)
    4684                 old_font = SelectObject(dc, font);
    4685         GetTextMetricsW(dc, &tm);
    4686         es->line_height = tm.tmHeight;
    4687         es->char_width = tm.tmAveCharWidth;
    4688         if (font)
    4689                 SelectObject(dc, old_font);
    4690         ReleaseDC(hwnd, dc);
    4691         if (font && (TWEAK_WineLook > WIN31_LOOK))
    4692                 EDIT_EM_SetMargins(es, EC_LEFTMARGIN | EC_RIGHTMARGIN,
    4693                                    EC_USEFONTINFO, EC_USEFONTINFO);
    4694 
    4695         /* Force the recalculation of the format rect for each font change */
    4696         GetClientRect(hwnd, &r);
    4697         EDIT_SetRectNP(hwnd, es, &r);
    4698 
    4699         if (es->style & ES_MULTILINE)
    4700                 EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
    4701         else
    4702             EDIT_CalcLineWidth_SL(hwnd, es);
    4703 
    4704         if (redraw)
    4705                 EDIT_UpdateText(hwnd, es, NULL, TRUE);
    4706         if (es->flags & EF_FOCUSED) {
    4707                 DestroyCaret();
    4708                 CreateCaret(hwnd, 0, 2, es->line_height);
    4709                 EDIT_SetCaretPos(hwnd, es, es->selection_end,
    4710                                 es->flags & EF_AFTER_WRAP);
    4711                 ShowCaret(hwnd);
    4712         }
    4713 }
    4714 
    4715 
    4716 /*********************************************************************
    4717  *
    4718  *      WM_SETTEXT
     4714    TEXTMETRICW tm;
     4715    HDC dc;
     4716    HFONT old_font = 0;
     4717    RECT r;
     4718
     4719    es->font = font;
     4720    dc = GetDC(hwnd);
     4721    if (font)
     4722        old_font = SelectObject(dc, font);
     4723    GetTextMetricsW(dc, &tm);
     4724    es->line_height = tm.tmHeight;
     4725    es->char_width = tm.tmAveCharWidth;
     4726    if (font)
     4727        SelectObject(dc, old_font);
     4728    ReleaseDC(hwnd, dc);
     4729    if (font && (TWEAK_WineLook > WIN31_LOOK))
     4730        EDIT_EM_SetMargins(es, EC_LEFTMARGIN | EC_RIGHTMARGIN,
     4731                   EC_USEFONTINFO, EC_USEFONTINFO);
     4732
     4733    /* Force the recalculation of the format rect for each font change */
     4734    GetClientRect(hwnd, &r);
     4735    EDIT_SetRectNP(hwnd, es, &r);
     4736
     4737    if (es->style & ES_MULTILINE)
     4738        EDIT_BuildLineDefs_ML(hwnd, es, 0, strlenW(es->text), 0, (HRGN)0);
     4739    else
     4740        EDIT_CalcLineWidth_SL(hwnd, es);
     4741
     4742    if (redraw)
     4743        EDIT_UpdateText(hwnd, es, NULL, TRUE);
     4744    if (es->flags & EF_FOCUSED) {
     4745        DestroyCaret();
     4746        CreateCaret(hwnd, 0, 2, es->line_height);
     4747        EDIT_SetCaretPos(hwnd, es, es->selection_end,
     4748                es->flags & EF_AFTER_WRAP);
     4749        ShowCaret(hwnd);
     4750    }
     4751}
     4752
     4753
     4754/*********************************************************************
     4755 *
     4756 *  WM_SETTEXT
    47194757 *
    47204758 * NOTES
     
    47314769
    47324770    if(unicode)
    4733         text = (LPWSTR)lParam;
     4771    text = (LPWSTR)lParam;
    47344772    else if (lParam)
    47354773    {
    4736         LPCSTR textA = (LPCSTR)lParam;
    4737         INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
    4738         if((text = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
    4739             MultiByteToWideChar(CP_ACP, 0, textA, -1, text, countW);
    4740     }
    4741 
    4742         EDIT_EM_SetSel(hwnd, es, 0, (UINT)-1, FALSE);
    4743         if (text) {
    4744                 TRACE("%s\n", debugstr_w(text));
    4745                 EDIT_EM_ReplaceSel(hwnd, es, FALSE, text, FALSE);
    4746                 if(!unicode)
    4747                     HeapFree(GetProcessHeap(), 0, text);
    4748         } else {
    4749                 static const WCHAR empty_stringW[] = {0};
    4750                 TRACE("<NULL>\n");
    4751                 EDIT_EM_ReplaceSel(hwnd, es, FALSE, empty_stringW, FALSE);
    4752         }
    4753         es->x_offset = 0;
    4754         es->flags &= ~EF_MODIFIED;
    4755         EDIT_EM_SetSel(hwnd, es, 0, 0, FALSE);
     4774    LPCSTR textA = (LPCSTR)lParam;
     4775    INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
     4776    if((text = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
     4777        MultiByteToWideChar(CP_ACP, 0, textA, -1, text, countW);
     4778    }
     4779
     4780    EDIT_EM_SetSel(hwnd, es, 0, (UINT)-1, FALSE);
     4781    if (text) {
     4782        TRACE("%s\n", debugstr_w(text));
     4783        EDIT_EM_ReplaceSel(hwnd, es, FALSE, text, FALSE);
     4784        if(!unicode)
     4785            HeapFree(GetProcessHeap(), 0, text);
     4786    } else {
     4787        static const WCHAR empty_stringW[] = {0};
     4788        TRACE("<NULL>\n");
     4789        EDIT_EM_ReplaceSel(hwnd, es, FALSE, empty_stringW, FALSE);
     4790    }
     4791    es->x_offset = 0;
     4792    es->flags &= ~EF_MODIFIED;
     4793    EDIT_EM_SetSel(hwnd, es, 0, 0, FALSE);
    47564794        /* Send the notification after the selection start and end have been set
    47574795         * edit control doesn't send notification on WM_SETTEXT
    47584796         * if it is multiline, or it is part of combobox
    47594797         */
    4760         if( !((es->style & ES_MULTILINE) || es->hwndListBox))
     4798    if( !((es->style & ES_MULTILINE) || es->hwndListBox))
    47614799       {
    4762             EDIT_NOTIFY_PARENT(hwnd, es, EN_CHANGE, "EN_CHANGE");
     4800        EDIT_NOTIFY_PARENT(hwnd, es, EN_CHANGE, "EN_CHANGE");
    47634801           EDIT_NOTIFY_PARENT(hwnd, es, EN_UPDATE, "EN_UPDATE");
    47644802       }
    4765         EDIT_EM_ScrollCaret(hwnd, es);
    4766 }
    4767 
    4768 
    4769 /*********************************************************************
    4770  *
    4771  *      WM_SIZE
     4803    EDIT_EM_ScrollCaret(hwnd, es);
     4804}
     4805
     4806
     4807/*********************************************************************
     4808 *
     4809 *  WM_SIZE
    47724810 *
    47734811 */
    47744812static void EDIT_WM_Size(HWND hwnd, EDITSTATE *es, UINT action, INT width, INT height)
    47754813{
    4776         if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
    4777                 RECT rc;
    4778                 TRACE("width = %d, height = %d\n", width, height);
    4779                 SetRect(&rc, 0, 0, width, height);
    4780                 EDIT_SetRectNP(hwnd, es, &rc);
    4781                 EDIT_UpdateText(hwnd, es, NULL, TRUE);
    4782         }
    4783 }
    4784 
    4785 
    4786 /*********************************************************************
    4787  *
    4788  *      WM_STYLECHANGED
     4814    if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
     4815        RECT rc;
     4816        TRACE("width = %d, height = %d\n", width, height);
     4817        SetRect(&rc, 0, 0, width, height);
     4818        EDIT_SetRectNP(hwnd, es, &rc);
     4819        EDIT_UpdateText(hwnd, es, NULL, TRUE);
     4820    }
     4821}
     4822
     4823
     4824/*********************************************************************
     4825 *
     4826 *  WM_STYLECHANGED
    47894827 *
    47904828 * This message is sent by SetWindowLong on having changed either the Style
     
    48464884/*********************************************************************
    48474885 *
    4848  *      WM_SYSKEYDOWN
     4886 *  WM_SYSKEYDOWN
    48494887 *
    48504888 */
    48514889static LRESULT EDIT_WM_SysKeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data)
    48524890{
    4853         if ((key == VK_BACK) && (key_data & 0x2000)) {
    4854                 if (EDIT_EM_CanUndo(es))
    4855                         EDIT_EM_Undo(hwnd, es);
    4856                 return 0;
    4857         } else if (key == VK_UP || key == VK_DOWN) {
    4858                 if (EDIT_CheckCombo(hwnd, es, WM_SYSKEYDOWN, key))
    4859                         return 0;
    4860         }
    4861         return DefWindowProcW(hwnd, WM_SYSKEYDOWN, (WPARAM)key, (LPARAM)key_data);
    4862 }
    4863 
    4864 
    4865 /*********************************************************************
    4866  *
    4867  *      WM_TIMER
     4891    if ((key == VK_BACK) && (key_data & 0x2000)) {
     4892        if (EDIT_EM_CanUndo(es))
     4893            EDIT_EM_Undo(hwnd, es);
     4894        return 0;
     4895    } else if (key == VK_UP || key == VK_DOWN) {
     4896        if (EDIT_CheckCombo(hwnd, es, WM_SYSKEYDOWN, key))
     4897            return 0;
     4898    }
     4899    return DefWindowProcW(hwnd, WM_SYSKEYDOWN, (WPARAM)key, (LPARAM)key_data);
     4900}
     4901
     4902
     4903/*********************************************************************
     4904 *
     4905 *  WM_TIMER
    48684906 *
    48694907 */
    48704908static void EDIT_WM_Timer(HWND hwnd, EDITSTATE *es)
    48714909{
    4872         if (es->region_posx < 0) {
    4873                 EDIT_MoveBackward(hwnd, es, TRUE);
    4874         } else if (es->region_posx > 0) {
    4875                 EDIT_MoveForward(hwnd, es, TRUE);
    4876         }
     4910    if (es->region_posx < 0) {
     4911        EDIT_MoveBackward(hwnd, es, TRUE);
     4912    } else if (es->region_posx > 0) {
     4913        EDIT_MoveForward(hwnd, es, TRUE);
     4914    }
    48774915/*
    4878  *      FIXME: gotta do some vertical scrolling here, like
    4879  *              EDIT_EM_LineScroll(hwnd, 0, 1);
    4880  */
    4881 }
    4882 
    4883 /*********************************************************************
    4884  *
    4885  *      WM_VSCROLL
     4916 *  FIXME: gotta do some vertical scrolling here, like
     4917 *      EDIT_EM_LineScroll(hwnd, 0, 1);
     4918 */
     4919}
     4920
     4921/*********************************************************************
     4922 *
     4923 *  WM_VSCROLL
    48864924 *
    48874925 */
    48884926static LRESULT EDIT_WM_VScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos)
    48894927{
    4890         INT dy;
    4891 
    4892         if (!(es->style & ES_MULTILINE))
    4893                 return 0;
    4894 
    4895         if (!(es->style & ES_AUTOVSCROLL))
    4896                 return 0;
    4897 
    4898         dy = 0;
    4899         switch (action) {
    4900         case SB_LINEUP:
    4901         case SB_LINEDOWN:
    4902         case SB_PAGEUP:
    4903         case SB_PAGEDOWN:
    4904                 TRACE("action %d\n", action);
    4905                 EDIT_EM_Scroll(hwnd, es, action);
    4906                 return 0;
    4907         case SB_TOP:
    4908                 TRACE("SB_TOP\n");
    4909                 dy = -es->y_offset;
    4910                 break;
    4911         case SB_BOTTOM:
    4912                 TRACE("SB_BOTTOM\n");
    4913                 dy = es->line_count - 1 - es->y_offset;
    4914                 break;
    4915         case SB_THUMBTRACK:
    4916                 TRACE("SB_THUMBTRACK %d\n", pos);
    4917                 es->flags |= EF_VSCROLL_TRACK;
    4918                 if(es->style & WS_VSCROLL)
    4919                     dy = pos - es->y_offset;
    4920                 else
    4921                 {
    4922                     /* Assume default scroll range 0-100 */
    4923                     INT vlc, new_y;
    4924                     /* Sanity check */
    4925                     if(pos < 0 || pos > 100) return 0;
    4926                     vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    4927                     new_y = pos * (es->line_count - vlc) / 100;
    4928                     dy = es->line_count ? (new_y - es->y_offset) : 0;
    4929                     TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
    4930                             es->line_count, es->y_offset, pos, dy);
    4931                 }
    4932                 break;
    4933         case SB_THUMBPOSITION:
    4934                 TRACE("SB_THUMBPOSITION %d\n", pos);
    4935                 es->flags &= ~EF_VSCROLL_TRACK;
    4936                 if(es->style & WS_VSCROLL)
    4937                     dy = pos - es->y_offset;
    4938                 else
    4939                 {
    4940                     /* Assume default scroll range 0-100 */
    4941                     INT vlc, new_y;
    4942                     /* Sanity check */
    4943                     if(pos < 0 || pos > 100) return 0;
    4944                     vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    4945                     new_y = pos * (es->line_count - vlc) / 100;
    4946                     dy = es->line_count ? (new_y - es->y_offset) : 0;
    4947                     TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
    4948                             es->line_count, es->y_offset, pos, dy);
    4949                 }
    4950                 if (!dy)
    4951                 {
    4952                         /* force scroll info update */
    4953                         EDIT_UpdateScrollInfo(hwnd, es);
    4954                         EDIT_NOTIFY_PARENT(hwnd, es, EN_VSCROLL, "EN_VSCROLL");
    4955                 }
    4956                 break;
    4957         case SB_ENDSCROLL:
    4958                 TRACE("SB_ENDSCROLL\n");
    4959                 break;
    4960         /*
    4961          *      FIXME : the next two are undocumented !
    4962          *      Are we doing the right thing ?
    4963          *      At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
    4964          *      although it's also a regular control message.
    4965         */
    4966         case EM_GETTHUMB: /* this one is used by NT notepad */
    4967         case EM_GETTHUMB16:
    4968         {
    4969                 LRESULT ret;
    4970                 if(GetWindowLongA( hwnd, GWL_STYLE ) & WS_VSCROLL)
    4971                     ret = GetScrollPos(hwnd, SB_VERT);
    4972                 else
    4973                 {
    4974                     /* Assume default scroll range 0-100 */
    4975                     INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
    4976                     ret = es->line_count ? es->y_offset * 100 / (es->line_count - vlc) : 0;
    4977                 }
    4978                 TRACE("EM_GETTHUMB: returning %ld\n", ret);
    4979                 return ret;
    4980         }
    4981         case EM_LINESCROLL16:
    4982                 TRACE("EM_LINESCROLL16 %d\n", pos);
    4983                 dy = pos;
    4984                 break;
    4985 
    4986         default:
    4987                 ERR("undocumented WM_VSCROLL action %d (0x%04x), please report\n",
     4928    INT dy;
     4929
     4930    if (!(es->style & ES_MULTILINE))
     4931        return 0;
     4932
     4933    if (!(es->style & ES_AUTOVSCROLL))
     4934        return 0;
     4935
     4936    dy = 0;
     4937    switch (action) {
     4938    case SB_LINEUP:
     4939    case SB_LINEDOWN:
     4940    case SB_PAGEUP:
     4941    case SB_PAGEDOWN:
     4942        TRACE("action %d\n", action);
     4943        EDIT_EM_Scroll(hwnd, es, action);
     4944        return 0;
     4945    case SB_TOP:
     4946        TRACE("SB_TOP\n");
     4947        dy = -es->y_offset;
     4948        break;
     4949    case SB_BOTTOM:
     4950        TRACE("SB_BOTTOM\n");
     4951        dy = es->line_count - 1 - es->y_offset;
     4952        break;
     4953    case SB_THUMBTRACK:
     4954        TRACE("SB_THUMBTRACK %d\n", pos);
     4955        es->flags |= EF_VSCROLL_TRACK;
     4956        if(es->style & WS_VSCROLL)
     4957            dy = pos - es->y_offset;
     4958        else
     4959        {
     4960            /* Assume default scroll range 0-100 */
     4961            INT vlc, new_y;
     4962            /* Sanity check */
     4963            if(pos < 0 || pos > 100) return 0;
     4964            vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     4965            new_y = pos * (es->line_count - vlc) / 100;
     4966            dy = es->line_count ? (new_y - es->y_offset) : 0;
     4967            TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
     4968                es->line_count, es->y_offset, pos, dy);
     4969        }
     4970        break;
     4971    case SB_THUMBPOSITION:
     4972        TRACE("SB_THUMBPOSITION %d\n", pos);
     4973        es->flags &= ~EF_VSCROLL_TRACK;
     4974        if(es->style & WS_VSCROLL)
     4975            dy = pos - es->y_offset;
     4976        else
     4977        {
     4978            /* Assume default scroll range 0-100 */
     4979            INT vlc, new_y;
     4980            /* Sanity check */
     4981            if(pos < 0 || pos > 100) return 0;
     4982            vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     4983            new_y = pos * (es->line_count - vlc) / 100;
     4984            dy = es->line_count ? (new_y - es->y_offset) : 0;
     4985            TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
     4986                es->line_count, es->y_offset, pos, dy);
     4987        }
     4988        if (!dy)
     4989        {
     4990            /* force scroll info update */
     4991            EDIT_UpdateScrollInfo(hwnd, es);
     4992            EDIT_NOTIFY_PARENT(hwnd, es, EN_VSCROLL, "EN_VSCROLL");
     4993        }
     4994        break;
     4995    case SB_ENDSCROLL:
     4996        TRACE("SB_ENDSCROLL\n");
     4997        break;
     4998    /*
     4999     *  FIXME : the next two are undocumented !
     5000     *  Are we doing the right thing ?
     5001     *  At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
     5002     *  although it's also a regular control message.
     5003    */
     5004    case EM_GETTHUMB: /* this one is used by NT notepad */
     5005    case EM_GETTHUMB16:
     5006    {
     5007        LRESULT ret;
     5008        if(GetWindowLongA( hwnd, GWL_STYLE ) & WS_VSCROLL)
     5009            ret = GetScrollPos(hwnd, SB_VERT);
     5010        else
     5011        {
     5012            /* Assume default scroll range 0-100 */
     5013            INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
     5014            ret = es->line_count ? es->y_offset * 100 / (es->line_count - vlc) : 0;
     5015        }
     5016        TRACE("EM_GETTHUMB: returning %ld\n", ret);
     5017        return ret;
     5018    }
     5019    case EM_LINESCROLL16:
     5020        TRACE("EM_LINESCROLL16 %d\n", pos);
     5021        dy = pos;
     5022        break;
     5023
     5024    default:
     5025        ERR("undocumented WM_VSCROLL action %d (0x%04x), please report\n",
    49885026                    action, action);
    4989                 return 0;
    4990         }
    4991         if (dy)
    4992                 EDIT_EM_LineScroll(hwnd, es, 0, dy);
    4993         return 0;
    4994 }
    4995 
    4996 /*********************************************************************
    4997  *
    4998  *      EDIT_UpdateText
     5027        return 0;
     5028    }
     5029    if (dy)
     5030        EDIT_EM_LineScroll(hwnd, es, 0, dy);
     5031    return 0;
     5032}
     5033
     5034/*********************************************************************
     5035 *
     5036 *  EDIT_UpdateText
    49995037 *
    50005038 */
     
    50085046/*********************************************************************
    50095047 *
    5010  *      EDIT_UpdateText
     5048 *  EDIT_UpdateText
    50115049 *
    50125050 */
Note: See TracChangeset for help on using the changeset viewer.