00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029 #include <os2win.h>
00030 #include <string.h>
00031 #include "controls.h"
00032 #include "combo.h"
00033
00034 #define DBG_LOCALLOG DBG_edit
00035 #include "dbglocal.h"
00036
00037 #ifdef DEBUG
00038 char *GetMsgText(int Msg);
00039 #endif
00040
00041 #define BUFLIMIT_MULTI 65534
00042
00043 #define BUFLIMIT_SINGLE 32766
00044
00045 #ifdef __WIN32OS2__
00046 #define BUFLIMIT_SINGLE_NT 0x7FFFFFFF
00047 #endif
00048
00049
00050
00051 #define BUFSTART_MULTI 1024
00052 #define BUFSTART_SINGLE 256
00053 #define GROWLENGTH 64
00054 #define HSCROLL_FRACTION 3
00055
00056
00057
00058
00059 #define EF_MODIFIED 0x0001
00060 #define EF_FOCUSED 0x0002
00061 #define EF_UPDATE 0x0004
00062 #define EF_VSCROLL_TRACK 0x0008
00063 #define EF_HSCROLL_TRACK 0x0010
00064 #define EF_VSCROLL_HACK 0x0020
00065 #define EF_HSCROLL_HACK 0x0040
00066 #define EF_AFTER_WRAP 0x0080
00067
00068 #define EF_USE_SOFTBRK 0x0100
00069
00070 typedef enum
00071 {
00072 END_0 = 0,
00073 END_WRAP,
00074 END_HARD,
00075 END_SOFT
00076 } LINE_END;
00077
00078 typedef struct tagLINEDEF {
00079 INT length;
00080 INT net_length;
00081 LINE_END ending;
00082 INT width;
00083 struct tagLINEDEF *next;
00084 } LINEDEF;
00085
00086 typedef struct
00087 {
00088 HANDLE heap;
00089 LPSTR text;
00090 INT buffer_size;
00091 INT buffer_limit;
00092 HFONT font;
00093 INT x_offset;
00094
00095 INT line_height;
00096 INT char_width;
00097 DWORD style;
00098 WORD flags;
00099 INT undo_insert_count;
00100 INT undo_position;
00101 LPSTR undo_text;
00102 INT undo_buffer_size;
00103 INT selection_start;
00104 INT selection_end;
00105 CHAR password_char;
00106 INT left_margin;
00107 INT right_margin;
00108 RECT format_rect;
00109 INT region_posx;
00110 INT region_posy;
00111 EDITWORDBREAKPROCA word_break_procA;
00112 INT line_count;
00113 INT y_offset;
00114 BOOL bCaptureState;
00115 BOOL bEnableState;
00116 HWND hwndListBox;
00117
00118
00119
00120 INT lock_count;
00121 INT tabs_count;
00122 LPINT tabs;
00123 INT text_width;
00124 LINEDEF *first_line_def;
00125 HLOCAL hloc;
00126 } EDITSTATE;
00127
00128
00129 #define SWAP_INT32(x,y) do { INT temp = (INT)(x); (x) = (INT)(y); (y) = temp; } while(0)
00130 #define ORDER_INT(x,y) do { if ((INT)(y) < (INT)(x)) SWAP_INT32((x),(y)); } while(0)
00131
00132 #define SWAP_UINT32(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
00133 #define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT32((x),(y)); } while(0)
00134
00135
00136 #define EDIT_SEND_CTLCOLORSTATIC(hwnd,hdc) \
00137 (SendMessageA(GetParent(hwnd), WM_CTLCOLORSTATIC, \
00138 (WPARAM)(hdc), (LPARAM)hwnd))
00139 #define EDIT_SEND_CTLCOLOR(hwnd,hdc) \
00140 (SendMessageA(GetParent(hwnd), WM_CTLCOLOREDIT, \
00141 (WPARAM)(hdc), (LPARAM)hwnd))
00142 #define EDIT_NOTIFY_PARENT(hwnd, wNotifyCode) \
00143 (SendMessageA(GetParent(hwnd), WM_COMMAND, \
00144 MAKEWPARAM(GetWindowLongA(hwnd,GWL_ID), wNotifyCode), (LPARAM)hwnd))
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 static inline BOOL EDIT_EM_CanUndo(HWND hwnd, EDITSTATE *es);
00158 static inline void EDIT_EM_EmptyUndoBuffer(HWND hwnd, EDITSTATE *es);
00159 static inline void EDIT_WM_Clear(HWND hwnd, EDITSTATE *es);
00160 static inline void EDIT_WM_Cut(HWND hwnd, EDITSTATE *es);
00161
00162
00163
00164
00165 static void EDIT_BuildLineDefs_ML(HWND hwnd,EDITSTATE *es);
00166 static LPSTR EDIT_GetPasswordPointer_SL(HWND hwnd, EDITSTATE *es);
00167 static void EDIT_MoveDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
00168 static void EDIT_MovePageDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
00169 static void EDIT_MovePageUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
00170 static void EDIT_MoveUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend);
00171 static VOID EDIT_UpdateScrollBars(HWND hwnd,EDITSTATE *es,BOOL updateHorz,BOOL updateVert);
00172
00173
00174
00175 static INT EDIT_CallWordBreakProc(HWND hwnd, EDITSTATE *es, INT start, INT index, INT count, INT action);
00176 static INT EDIT_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap);
00177 static void EDIT_ConfinePoint(HWND hwnd, EDITSTATE *es, LPINT x, LPINT y);
00178 static void EDIT_GetLineRect(HWND hwnd,HDC dc,EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc);
00179 static void EDIT_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end);
00180 static void EDIT_LockBuffer(HWND hwnd, EDITSTATE *es);
00181 static BOOL EDIT_MakeFit(HWND hwnd, EDITSTATE *es, INT size);
00182 static BOOL EDIT_MakeUndoFit(HWND hwnd, EDITSTATE *es, INT size);
00183 static void EDIT_MoveBackward(HWND hwnd, EDITSTATE *es, BOOL extend);
00184 static void EDIT_MoveEnd(HWND hwnd, EDITSTATE *es, BOOL extend);
00185 static void EDIT_MoveForward(HWND hwnd, EDITSTATE *es, BOOL extend);
00186 static void EDIT_MoveHome(HWND hwnd, EDITSTATE *es, BOOL extend);
00187 static void EDIT_MoveWordBackward(HWND hwnd, EDITSTATE *es, BOOL extend);
00188 static void EDIT_MoveWordForward(HWND hwnd, EDITSTATE *es, BOOL extend);
00189 static void EDIT_PaintLine(HWND hwnd, EDITSTATE *es, HDC hdc, INT line, BOOL rev);
00190 static VOID EDIT_PaintText(HWND hwnd, EDITSTATE *es, HDC hdc, INT x, INT y, INT line, INT col, INT count, BOOL rev);
00191 static void EDIT_SetCaretPos(HWND hwnd, EDITSTATE *es, INT pos, BOOL after_wrap);
00192 static void EDIT_SetRectNP(HWND hwnd, EDITSTATE *es, LPRECT lprc);
00193 static void EDIT_UnlockBuffer(HWND hwnd, EDITSTATE *es, BOOL force);
00194 static INT EDIT_WordBreakProc(LPSTR s, INT index, INT count, INT action);
00195 static VOID EDIT_Draw(HWND hwnd,EDITSTATE *es,HDC hdc);
00196 static VOID EDIT_Refresh(HWND hwnd,EDITSTATE *es,BOOL useCache);
00197
00198
00199
00200
00201 static LRESULT EDIT_EM_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y);
00202 static BOOL EDIT_EM_FmtLines(HWND hwnd, EDITSTATE *es, BOOL add_eol);
00203 static INT EDIT_EM_GetFirstVisibleLine(HWND hwnd,EDITSTATE *es);
00204 static HLOCAL EDIT_EM_GetHandle(HWND hwnd, EDITSTATE *es);
00205 static INT EDIT_EM_GetLimitText(HWND hwnd,EDITSTATE *es);
00206 static INT EDIT_EM_GetLine(HWND hwnd, EDITSTATE *es, INT line, LPSTR lpch);
00207 static INT EDIT_EM_GetLineCount(HWND hwnd,EDITSTATE *es);
00208 static LONG EDIT_EM_GetMargins(HWND hwnd,EDITSTATE *es);
00209 static BOOL EDIT_EM_GetModify(HWND hwnd,EDITSTATE *es);
00210 static CHAR EDIT_EM_GetPasswordChar(HWND hwnd,EDITSTATE *es);
00211 static VOID EDIT_EM_GetRect(HWND hwnd,EDITSTATE *es,LPRECT lprc);
00212 static LRESULT EDIT_EM_GetSel(HWND hwnd, EDITSTATE *es, LPUINT start, LPUINT end);
00213 static LRESULT EDIT_EM_GetThumb(HWND hwnd, EDITSTATE *es);
00214 static PVOID EDIT_EM_GetWordbreakProc(HWND hwnd,EDITSTATE *es);
00215 static INT EDIT_EM_LineFromChar(HWND hwnd, EDITSTATE *es, INT index);
00216 static INT EDIT_EM_LineIndex(HWND hwnd, EDITSTATE *es, INT line);
00217 static INT EDIT_EM_LineLength(HWND hwnd, EDITSTATE *es, INT index);
00218 static BOOL EDIT_EM_LineScroll(HWND hwnd, EDITSTATE *es, INT dx, INT dy);
00219 static LRESULT EDIT_EM_PosFromChar(HWND hwnd,HDC dc, EDITSTATE *es, INT index, BOOL after_wrap);
00220 static void EDIT_EM_ReplaceSel(HWND hwnd, EDITSTATE *es, BOOL can_undo, LPCSTR lpsz_replace);
00221 static LRESULT EDIT_EM_Scroll(HWND hwnd, EDITSTATE *es, INT action);
00222 static void EDIT_EM_ScrollCaret(HWND hwnd, EDITSTATE *es);
00223 static void EDIT_EM_SetHandle(HWND hwnd, EDITSTATE *es, HLOCAL hloc);
00224 static void EDIT_EM_SetLimitText(HWND hwnd, EDITSTATE *es, INT limit);
00225 static void EDIT_EM_SetMargins(HWND hwnd, EDITSTATE *es, INT action, INT left, INT right);
00226 static void EDIT_EM_SetModify(HWND hwnd,EDITSTATE *es,BOOL fModified);
00227 static void EDIT_EM_SetPasswordChar(HWND hwnd, EDITSTATE *es, CHAR c);
00228 static BOOL EDIT_EM_SetReadOnly(HWND hwnd,EDITSTATE *es,BOOL fReadOnly);
00229 static void EDIT_EM_SetRect(HWND hwnd,EDITSTATE *es,LPRECT lprc);
00230 static void EDIT_EM_SetRectNP(HWND hwnd,EDITSTATE *es,LPRECT lprc);
00231 static void EDIT_EM_SetSel(HWND hwnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
00232 static BOOL EDIT_EM_SetTabStops(HWND hwnd, EDITSTATE *es, INT count, LPINT tabs);
00233 static void EDIT_EM_SetWordBreakProc(HWND hwnd, EDITSTATE *es, EDITWORDBREAKPROCA wbp);
00234 static BOOL EDIT_EM_Undo(HWND hwnd, EDITSTATE *es);
00235 static LRESULT EDIT_EM_SetIMEStatus(HWND hwnd,EDITSTATE *es,WPARAM wParam,LPARAM lParam);
00236 static LRESULT EDIT_EM_GetIMEStatus(HWND hwnd,EDITSTATE *es,WPARAM wParam,LPARAM lParam);
00237
00238
00239
00240 static void EDIT_WM_Char(HWND hwnd, EDITSTATE *es, CHAR c, DWORD key_data);
00241 static void EDIT_WM_Command(HWND hwnd, EDITSTATE *es, INT code, INT id, HWND conrtol);
00242 static void EDIT_WM_ContextMenu(HWND hwnd, EDITSTATE *es, HWND hwndBtn, INT x, INT y);
00243 static void EDIT_WM_Copy(HWND hwnd, EDITSTATE *es);
00244 static LRESULT EDIT_WM_Create(HWND hwnd, EDITSTATE *es, LPCREATESTRUCTA cs);
00245 static void EDIT_WM_Destroy(HWND hwnd, EDITSTATE *es);
00246 static LRESULT EDIT_WM_EraseBkGnd(HWND hwnd, EDITSTATE *es, HDC dc);
00247 static INT EDIT_WM_GetText(HWND hwnd, EDITSTATE *es, INT count, LPSTR text);
00248 static LRESULT EDIT_WM_HScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar);
00249 static LRESULT EDIT_WM_KeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data);
00250 static LRESULT EDIT_WM_KillFocus(HWND hwnd, EDITSTATE *es, HWND window_getting_focus);
00251 static LRESULT EDIT_WM_LButtonDblClk(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y);
00252 static LRESULT EDIT_WM_LButtonDown(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y);
00253 static LRESULT EDIT_WM_LButtonUp(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y);
00254 static LRESULT EDIT_WM_CaptureChanged(HWND hwnd,EDITSTATE *es);
00255 static LRESULT EDIT_WM_MouseMove(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y);
00256 static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTA cs);
00257 static void EDIT_WM_Paint(HWND hwnd, EDITSTATE *es,WPARAM wParam);
00258 static void EDIT_WM_Paste(HWND hwnd, EDITSTATE *es);
00259 static void EDIT_WM_SetFocus(HWND hwnd, EDITSTATE *es, HWND window_losing_focus);
00260 static void EDIT_WM_SetFont(HWND hwnd, EDITSTATE *es, HFONT font, BOOL redraw);
00261 static void EDIT_WM_SetText(HWND hwnd, EDITSTATE *es, LPCSTR text);
00262 static void EDIT_WM_Size(HWND hwnd, EDITSTATE *es, UINT action, INT width, INT height);
00263 static LRESULT EDIT_WM_SysKeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data);
00264 static void EDIT_WM_Timer(HWND hwnd, EDITSTATE *es, INT id, TIMERPROC timer_proc);
00265 static LRESULT EDIT_WM_VScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar);
00266 static LRESULT EDIT_WM_MouseWheel(HWND hwnd,EDITSTATE *es,WPARAM wParam,LPARAM lParam);
00267
00268
00269
00270
00271
00272
00273 static inline BOOL EDIT_EM_CanUndo(HWND hwnd, EDITSTATE *es)
00274 {
00275 return (es->undo_insert_count || lstrlenA(es->undo_text));
00276 }
00277
00278
00279
00280
00281
00282
00283
00284 static inline void EDIT_EM_EmptyUndoBuffer(HWND hwnd, EDITSTATE *es)
00285 {
00286 es->undo_insert_count = 0;
00287 *es->undo_text = '\0';
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 static inline void EDIT_WM_Clear(HWND hwnd, EDITSTATE *es)
00297 {
00298 EDIT_EM_ReplaceSel(hwnd, es, TRUE, "");
00299 if (es->flags & EF_UPDATE) {
00300 es->flags &= ~EF_UPDATE;
00301 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 static inline void EDIT_WM_Cut(HWND hwnd, EDITSTATE *es)
00312 {
00313 EDIT_WM_Copy(hwnd, es);
00314 EDIT_WM_Clear(hwnd, es);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 LRESULT WINAPI EditWndProc( HWND hwnd, UINT msg,
00332 WPARAM wParam, LPARAM lParam )
00333 {
00334 EDITSTATE *es = (EDITSTATE*)GetInfoPtr(hwnd);
00335 LRESULT result = 0;
00336
00337
00338
00339
00340 switch (msg) {
00341 case WM_DESTROY:
00342
00343 EDIT_WM_Destroy(hwnd, es);
00344 result = 0;
00345 goto END;
00346
00347 case WM_NCCREATE:
00348
00349 result = EDIT_WM_NCCreate(hwnd, (LPCREATESTRUCTA)lParam);
00350 goto END;
00351 }
00352
00353 if (!es)
00354 {
00355 result = DefWindowProcA(hwnd, msg, wParam, lParam);
00356 goto END;
00357 }
00358
00359
00360 EDIT_LockBuffer(hwnd, es);
00361 switch (msg) {
00362 case EM_GETSEL:
00363
00364 result = EDIT_EM_GetSel(hwnd, es, (LPUINT)wParam, (LPUINT)lParam);
00365 break;
00366
00367 case EM_SETSEL:
00368
00369 EDIT_EM_SetSel(hwnd, es, wParam, lParam, FALSE);
00370 EDIT_EM_ScrollCaret(hwnd,es);
00371 result = 1;
00372 break;
00373
00374 case EM_GETRECT:
00375
00376 EDIT_EM_GetRect(hwnd,es,(LPRECT)lParam);
00377 break;
00378
00379 case EM_SETRECT:
00380
00381 EDIT_EM_SetRect(hwnd,es,(LPRECT)lParam);
00382 break;
00383
00384 case EM_SETRECTNP:
00385
00386 EDIT_EM_SetRectNP(hwnd,es,(LPRECT)lParam);
00387 break;
00388
00389 case EM_SCROLL:
00390
00391 result = EDIT_EM_Scroll(hwnd, es, (INT)wParam);
00392 break;
00393
00394 case EM_LINESCROLL:
00395
00396 result = (LRESULT)EDIT_EM_LineScroll(hwnd, es, (INT)wParam, (INT)lParam);
00397 break;
00398
00399 case EM_SCROLLCARET:
00400
00401 EDIT_EM_ScrollCaret(hwnd, es);
00402 result = 1;
00403 break;
00404
00405 case EM_GETMODIFY:
00406
00407 result = (LRESULT)EDIT_EM_GetModify(hwnd,es);
00408 break;
00409
00410 case EM_SETMODIFY:
00411
00412 EDIT_EM_SetModify(hwnd,es,(BOOL)wParam);
00413 break;
00414
00415 case EM_GETLINECOUNT:
00416
00417 result = (LRESULT)EDIT_EM_GetLineCount(hwnd,es);
00418 break;
00419
00420 case EM_LINEINDEX:
00421
00422 result = (LRESULT)EDIT_EM_LineIndex(hwnd, es, (INT)wParam);
00423 break;
00424
00425 case EM_SETHANDLE:
00426
00427 EDIT_EM_SetHandle(hwnd, es, (HLOCAL)wParam);
00428 break;
00429
00430 case EM_GETHANDLE:
00431
00432 result = (LRESULT)EDIT_EM_GetHandle(hwnd, es);
00433 break;
00434
00435 case EM_GETTHUMB:
00436
00437 result = EDIT_EM_GetThumb(hwnd, es);
00438 break;
00439
00440
00441
00442 case WM_USER+15:
00443
00444
00445 case 0x00bf:
00446
00447 result = DefWindowProcA(hwnd, msg, wParam, lParam);
00448 break;
00449
00450 case WM_USER+16:
00451
00452
00453 case 0x00c0:
00454
00455 result = DefWindowProcA(hwnd, msg, wParam, lParam);
00456 break;
00457
00458 case EM_LINELENGTH:
00459
00460 result = (LRESULT)EDIT_EM_LineLength(hwnd, es, (INT)wParam);
00461 break;
00462
00463 case EM_REPLACESEL:
00464
00465 EDIT_EM_ReplaceSel(hwnd, es, (BOOL)wParam, (LPCSTR)lParam);
00466 result = 1;
00467 break;
00468
00469
00470
00471 case WM_USER+19:
00472
00473
00474 case 0x00c3:
00475
00476 result = DefWindowProcA(hwnd, msg, wParam, lParam);
00477 break;
00478
00479 case EM_GETLINE:
00480
00481 result = (LRESULT)EDIT_EM_GetLine(hwnd, es, (INT)wParam, (LPSTR)lParam);
00482 break;
00483
00484 case EM_SETLIMITTEXT:
00485
00486 EDIT_EM_SetLimitText(hwnd, es, (INT)wParam);
00487 break;
00488
00489 case EM_CANUNDO:
00490
00491 result = (LRESULT)EDIT_EM_CanUndo(hwnd, es);
00492 break;
00493
00494 case EM_UNDO:
00495
00496 case WM_UNDO:
00497
00498 result = (LRESULT)EDIT_EM_Undo(hwnd, es);
00499 break;
00500
00501 case EM_FMTLINES:
00502
00503 result = (LRESULT)EDIT_EM_FmtLines(hwnd, es, (BOOL)wParam);
00504 break;
00505
00506 case EM_LINEFROMCHAR:
00507
00508 result = (LRESULT)EDIT_EM_LineFromChar(hwnd, es, (INT)wParam);
00509 break;
00510
00511
00512
00513 case WM_USER+26:
00514
00515
00516 case 0x00ca:
00517
00518 result = DefWindowProcA(hwnd, msg, wParam, lParam);
00519 break;
00520
00521 case EM_SETTABSTOPS:
00522
00523 result = (LRESULT)EDIT_EM_SetTabStops(hwnd, es, (INT)wParam, (LPINT)lParam);
00524 break;
00525
00526 case EM_SETPASSWORDCHAR:
00527
00528 EDIT_EM_SetPasswordChar(hwnd, es, (CHAR)wParam);
00529 break;
00530
00531 case EM_EMPTYUNDOBUFFER:
00532
00533 EDIT_EM_EmptyUndoBuffer(hwnd, es);
00534 break;
00535
00536 case EM_GETFIRSTVISIBLELINE:
00537
00538 result = (LRESULT)EDIT_EM_GetFirstVisibleLine(hwnd,es);
00539 break;
00540
00541 case EM_SETREADONLY:
00542
00543 result = (LRESULT)EDIT_EM_SetReadOnly(hwnd,es,(BOOL)wParam);
00544 break;
00545
00546 case EM_SETWORDBREAKPROC:
00547
00548 EDIT_EM_SetWordBreakProc(hwnd, es, (EDITWORDBREAKPROCA)lParam);
00549 break;
00550
00551 case EM_GETWORDBREAKPROC:
00552
00553 result = (LRESULT)EDIT_EM_GetWordbreakProc(hwnd,es);
00554 break;
00555
00556 case EM_GETPASSWORDCHAR:
00557
00558 result = (LRESULT)EDIT_EM_GetPasswordChar(hwnd,es);
00559 break;
00560
00561
00562
00563 case EM_SETMARGINS:
00564
00565 EDIT_EM_SetMargins(hwnd, es, (INT)wParam, SLOWORD(lParam), SHIWORD(lParam));
00566 break;
00567
00568 case EM_GETMARGINS:
00569
00570 result = EDIT_EM_GetMargins(hwnd,es);
00571 break;
00572
00573 case EM_GETLIMITTEXT:
00574
00575 result = (LRESULT)EDIT_EM_GetLimitText(hwnd,es);
00576 break;
00577
00578 case EM_POSFROMCHAR:
00579
00580 result = EDIT_EM_PosFromChar(hwnd,0, es, (INT)wParam, FALSE);
00581 break;
00582
00583 case EM_CHARFROMPOS:
00584
00585 result = EDIT_EM_CharFromPos(hwnd, es, SLOWORD(lParam), SHIWORD(lParam));
00586 break;
00587
00588 case EM_SETIMESTATUS:
00589 result = EDIT_EM_SetIMEStatus(hwnd,es,wParam,lParam);
00590 break;
00591
00592 case EM_GETIMESTATUS:
00593 result = EDIT_EM_GetIMEStatus(hwnd,es,wParam,lParam);
00594 break;
00595
00596 case WM_GETDLGCODE:
00597
00598 result = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
00599
00600 if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
00601 {
00602 int vk = (int)((LPMSG)lParam)->wParam;
00603
00604 if ((GetWindowLongA(hwnd,GWL_STYLE) & ES_WANTRETURN) && vk == VK_RETURN)
00605 {
00606 result |= DLGC_WANTMESSAGE;
00607 }
00608 else if (es->hwndListBox && (vk == VK_RETURN || vk == VK_ESCAPE))
00609 {
00610 if (SendMessageA(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0))
00611 result |= DLGC_WANTMESSAGE;
00612 }
00613 }
00614 break;
00615
00616 case WM_CHAR:
00617
00618 if (((CHAR)wParam == VK_RETURN || (CHAR)wParam == VK_ESCAPE) && es->hwndListBox)
00619 {
00620 HWND hwndParent = GetParent(hwnd);
00621
00622 if (SendMessageA(hwndParent, CB_GETDROPPEDSTATE, 0, 0))
00623 SendMessageA(hwndParent, WM_KEYDOWN, wParam, 0);
00624 break;
00625 }
00626 EDIT_WM_Char(hwnd, es, (CHAR)wParam, (DWORD)lParam);
00627 break;
00628
00629 case WM_CLEAR:
00630
00631 EDIT_WM_Clear(hwnd, es);
00632 break;
00633
00634 case WM_COMMAND:
00635
00636 EDIT_WM_Command(hwnd, es, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);
00637 break;
00638
00639 case WM_CONTEXTMENU:
00640
00641 EDIT_WM_ContextMenu(hwnd, es, (HWND)wParam, SLOWORD(lParam), SHIWORD(lParam));
00642 break;
00643
00644 case WM_COPY:
00645
00646 EDIT_WM_Copy(hwnd, es);
00647 break;
00648
00649 case WM_CREATE:
00650
00651 result = EDIT_WM_Create(hwnd, es, (LPCREATESTRUCTA)lParam);
00652 break;
00653
00654 case WM_CUT:
00655
00656 EDIT_WM_Cut(hwnd, es);
00657 break;
00658
00659 case WM_ENABLE:
00660
00661 es->bEnableState = (BOOL)wParam;
00662 EDIT_Refresh(hwnd,es,FALSE);
00663 break;
00664
00665 case WM_ERASEBKGND:
00666
00667 result = EDIT_WM_EraseBkGnd(hwnd, es, (HDC)wParam);
00668 break;
00669
00670 case WM_GETFONT:
00671
00672 result = (LRESULT)es->font;
00673 break;
00674
00675 case WM_GETTEXT:
00676
00677 result = (LRESULT)EDIT_WM_GetText(hwnd, es, (INT)wParam, (LPSTR)lParam);
00678 break;
00679
00680 case WM_GETTEXTLENGTH:
00681
00682 result = lstrlenA(es->text);
00683 break;
00684
00685 case WM_HSCROLL:
00686
00687 result = EDIT_WM_HScroll(hwnd, es, LOWORD(wParam), SHIWORD(wParam), (HWND)lParam);
00688 break;
00689
00690 case WM_KEYDOWN:
00691
00692 result = EDIT_WM_KeyDown(hwnd, es, (INT)wParam, (DWORD)lParam);
00693 break;
00694
00695 case WM_KILLFOCUS:
00696
00697 result = EDIT_WM_KillFocus(hwnd, es, (HWND)wParam);
00698 break;
00699
00700 case WM_LBUTTONDBLCLK:
00701
00702 result = EDIT_WM_LButtonDblClk(hwnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
00703 break;
00704
00705 case WM_LBUTTONDOWN:
00706
00707 result = EDIT_WM_LButtonDown(hwnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
00708 break;
00709
00710 case WM_LBUTTONUP:
00711
00712 result = EDIT_WM_LButtonUp(hwnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
00713 break;
00714
00715 case WM_CAPTURECHANGED:
00716 result = EDIT_WM_CaptureChanged(hwnd,es);
00717 break;
00718
00719 case WM_MOUSEACTIVATE:
00720
00721
00722
00723
00724
00725
00726
00727 result = MA_ACTIVATE;
00728 break;
00729
00730 case WM_MOUSEMOVE:
00731
00732
00733
00734 result = EDIT_WM_MouseMove(hwnd, es, (DWORD)wParam, SLOWORD(lParam), SHIWORD(lParam));
00735 break;
00736
00737 case WM_PAINT:
00738
00739 EDIT_WM_Paint(hwnd, es,wParam);
00740 break;
00741
00742 case WM_PASTE:
00743
00744 EDIT_WM_Paste(hwnd, es);
00745 break;
00746
00747 case WM_SETFOCUS:
00748
00749 EDIT_WM_SetFocus(hwnd, es, (HWND)wParam);
00750 break;
00751
00752 case WM_SETFONT:
00753
00754 EDIT_WM_SetFont(hwnd, es, (HFONT)wParam, LOWORD(lParam) != 0);
00755 break;
00756
00757 case WM_SETTEXT:
00758
00759 EDIT_WM_SetText(hwnd, es, (LPCSTR)lParam);
00760 result = TRUE;
00761 break;
00762
00763 case WM_SIZE:
00764
00765 EDIT_WM_Size(hwnd, es, (UINT)wParam, LOWORD(lParam), HIWORD(lParam));
00766 break;
00767
00768 case WM_SYSKEYDOWN:
00769
00770 result = EDIT_WM_SysKeyDown(hwnd, es, (INT)wParam, (DWORD)lParam);
00771 break;
00772
00773 case WM_TIMER:
00774
00775 EDIT_WM_Timer(hwnd, es, (INT)wParam, (TIMERPROC)lParam);
00776 break;
00777
00778 case WM_VSCROLL:
00779
00780 result = EDIT_WM_VScroll(hwnd, es, LOWORD(wParam), SHIWORD(wParam), (HWND)(lParam));
00781 break;
00782
00783 case WM_MOUSEWHEEL:
00784 result = EDIT_WM_MouseWheel(hwnd,es,wParam,lParam);
00785 break;
00786
00787 default:
00788 result = DefWindowProcA(hwnd, msg, wParam, lParam);
00789 break;
00790 }
00791 EDIT_UnlockBuffer(hwnd, es, FALSE);
00792 END:
00793 return result;
00794
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 static void EDIT_BuildLineDefs_ML(HWND hwnd,EDITSTATE *es)
00808 {
00809 HDC hdc = 0;
00810 HFONT old_font = 0;
00811 LPSTR start, cp;
00812 INT fw;
00813 LINEDEF *current_def;
00814 LINEDEF **previous_next;
00815
00816 current_def = es->first_line_def;
00817 do {
00818 LINEDEF *next_def = current_def->next;
00819 HeapFree(es->heap, 0, current_def);
00820 current_def = next_def;
00821 } while (current_def);
00822 es->line_count = 0;
00823 es->text_width = 0;
00824
00825 fw = es->format_rect.right - es->format_rect.left;
00826 start = es->text;
00827 previous_next = &es->first_line_def;
00828 do {
00829 current_def = (LINEDEF*)HeapAlloc(es->heap, 0, sizeof(LINEDEF));
00830 current_def->next = NULL;
00831 cp = start;
00832 while (*cp) {
00833 if ((*cp == '\r') && (*(cp + 1) == '\n'))
00834 break;
00835 cp++;
00836 }
00837 if (!(*cp)) {
00838 current_def->ending = END_0;
00839 current_def->net_length = lstrlenA(start);
00840 } else if ((cp > start) && (*(cp - 1) == '\r')) {
00841 current_def->ending = END_SOFT;
00842 current_def->net_length = cp - start - 1;
00843 } else {
00844 current_def->ending = END_HARD;
00845 current_def->net_length = cp - start;
00846 }
00847
00848 if (!hdc)
00849 {
00850 hdc = GetDC(hwnd);
00851 if (es->font)
00852 old_font = SelectObject(hdc, es->font);
00853 }
00854
00855 current_def->width = (INT)LOWORD(GetTabbedTextExtentA(hdc,
00856 start, current_def->net_length,
00857 es->tabs_count, es->tabs));
00858
00859 if ((!(es->style & ES_AUTOHSCROLL)) && (current_def->width > fw)) {
00860 INT next = 0;
00861 INT prev;
00862 do {
00863 prev = next;
00864 next = EDIT_CallWordBreakProc(hwnd, es, start - es->text,
00865 prev + 1, current_def->net_length, WB_RIGHT);
00866 current_def->width = (INT)LOWORD(GetTabbedTextExtentA(hdc,
00867 start, next, es->tabs_count, es->tabs));
00868 } while (current_def->width <= fw);
00869 if (!prev) {
00870 next = 0;
00871 do {
00872 prev = next;
00873 next++;
00874 current_def->width = (INT)LOWORD(GetTabbedTextExtentA(hdc,
00875 start, next, es->tabs_count, es->tabs));
00876 } while (current_def->width <= fw);
00877 if (!prev)
00878 prev = 1;
00879 }
00880 current_def->net_length = prev;
00881 current_def->ending = END_WRAP;
00882 current_def->width = (INT)LOWORD(GetTabbedTextExtentA(hdc, start,
00883 current_def->net_length, es->tabs_count, es->tabs));
00884 }
00885 switch (current_def->ending) {
00886 case END_SOFT:
00887 current_def->length = current_def->net_length + 3;
00888 break;
00889 case END_HARD:
00890 current_def->length = current_def->net_length + 2;
00891 break;
00892 case END_WRAP:
00893 case END_0:
00894 current_def->length = current_def->net_length;
00895 break;
00896 }
00897 es->text_width = MAX(es->text_width, current_def->width);
00898 start += current_def->length;
00899 *previous_next = current_def;
00900 previous_next = ¤t_def->next;
00901 es->line_count++;
00902 } while (current_def->ending != END_0);
00903 if (hdc)
00904 {
00905 if (es->font)
00906 SelectObject(hdc, old_font);
00907 ReleaseDC(hwnd, hdc);
00908 }
00909 EDIT_UpdateScrollBars(hwnd,es,TRUE,TRUE);
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926 static INT EDIT_CallWordBreakProc(HWND hwnd, EDITSTATE *es, INT start, INT index, INT count, INT action)
00927 {
00928 if (es->word_break_procA)
00929 {
00930
00931
00932
00933 return (INT)es->word_break_procA( es->text + start, index,
00934 count, action );
00935 }
00936 else
00937 return EDIT_WordBreakProc(es->text + start, index, count, action);
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951 static INT EDIT_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
00952 {
00953 INT index;
00954 HDC dc = 0;
00955 HFONT old_font = 0;
00956
00957 if (es->style & ES_MULTILINE) {
00958 INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
00959 INT line_index = 0;
00960 LINEDEF *line_def = es->first_line_def;
00961 INT low, high;
00962 while ((line > 0) && line_def->next) {
00963 line_index += line_def->length;
00964 line_def = line_def->next;
00965 line--;
00966 }
00967 x += es->x_offset - es->format_rect.left;
00968 if (x >= line_def->width) {
00969 if (after_wrap)
00970 *after_wrap = (line_def->ending == END_WRAP);
00971 return line_index + line_def->net_length;
00972 }
00973 if (x <= 0) {
00974 if (after_wrap)
00975 *after_wrap = FALSE;
00976 return line_index;
00977 }
00978 low = line_index + 1;
00979 high = line_index + line_def->net_length + 1;
00980 if (low < high-1)
00981 {
00982 if (!dc)
00983 {
00984 dc = GetDC(hwnd);
00985 if (es->font)
00986 old_font = SelectObject(dc, es->font);
00987 }
00988
00989 while (low < high-1)
00990 {
00991 INT mid = (low + high) / 2;
00992 if (LOWORD(GetTabbedTextExtentA(dc, es->text + line_index,mid - line_index, es->tabs_count, es->tabs)) > x) high = mid;
00993 else low = mid;
00994 }
00995 }
00996 index = low;
00997
00998 if (after_wrap)
00999 *after_wrap = ((index == line_index + line_def->net_length) &&
01000 (line_def->ending == END_WRAP));
01001 } else {
01002 LPSTR text;
01003 SIZE size;
01004 if (after_wrap)
01005 *after_wrap = FALSE;
01006 x -= es->format_rect.left;
01007 if (!x)
01008 return es->x_offset;
01009 text = EDIT_GetPasswordPointer_SL(hwnd, es);
01010 if (x < 0)
01011 {
01012 INT low = 0;
01013 INT high = es->x_offset;
01014
01015 if (low < high-1)
01016 {
01017 if (!dc)
01018 {
01019 dc = GetDC(hwnd);
01020 if (es->font)
01021 old_font = SelectObject(dc, es->font);
01022 }
01023
01024 while (low < high-1)
01025 {
01026 INT mid = (low + high) / 2;
01027
01028 GetTextExtentPoint32A( dc, text + mid,
01029 es->x_offset - mid, &size );
01030 if (size.cx > -x) low = mid;
01031 else high = mid;
01032 }
01033 }
01034 index = low;
01035 } else
01036 {
01037 INT low = es->x_offset;
01038 INT high = lstrlenA(es->text) + 1;
01039
01040 if (low < high-1)
01041 {
01042 if (!dc)
01043 {
01044 dc = GetDC(hwnd);
01045 if (es->font)
01046 old_font = SelectObject(dc, es->font);
01047 }
01048
01049 while (low < high-1)
01050 {
01051 INT mid = (low + high) / 2;
01052
01053 GetTextExtentPoint32A( dc, text + es->x_offset,
01054 mid - es->x_offset, &size );
01055 if (size.cx > x) high = mid;
01056 else low = mid;
01057 }
01058 }
01059 index = low;
01060 }
01061 if (es->style & ES_PASSWORD)
01062 HeapFree(es->heap, 0 ,text);
01063 }
01064 if (dc)
01065 {
01066 if (es->font)
01067 SelectObject(dc, old_font);
01068 ReleaseDC(hwnd, dc);
01069 }
01070 return index;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082 static void EDIT_ConfinePoint(HWND hwnd, EDITSTATE *es, LPINT x, LPINT y)
01083 {
01084 *x = MIN(MAX(*x, es->format_rect.left), es->format_rect.right - 1);
01085 *y = MIN(MAX(*y, es->format_rect.top), es->format_rect.bottom - 1);
01086 }
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 static void EDIT_GetLineRect(HWND hwnd,HDC dc,EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
01098 {
01099 INT line_index = EDIT_EM_LineIndex(hwnd, es, line);
01100
01101 if (es->style & ES_MULTILINE)
01102 rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
01103 else
01104 rc->top = es->format_rect.top;
01105 rc->bottom = rc->top + es->line_height;
01106
01107 rc->left = (scol == 0) ? es->format_rect.left : SLOWORD(EDIT_EM_PosFromChar(hwnd,dc, es, line_index + scol, TRUE));
01108 rc->right = (ecol == -1) ? es->format_rect.right : SLOWORD(EDIT_EM_PosFromChar(hwnd,dc, es, line_index + ecol, TRUE))+1;
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 static LPSTR EDIT_GetPasswordPointer_SL(HWND hwnd, EDITSTATE *es)
01120 {
01121 if (es->style & ES_PASSWORD) {
01122 INT len = lstrlenA(es->text);
01123 LPSTR text = (LPSTR)HeapAlloc(es->heap, 0, len + 1);
01124 RtlFillMemory(text, len, es->password_char);
01125 text[len] = '\0';
01126 return text;
01127 } else
01128 return es->text;
01129 }
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 static void EDIT_LockBuffer(HWND hwnd, EDITSTATE *es)
01141 {
01142 if (!es) {
01143
01144 return;
01145 }
01146 if (!(es->style & ES_MULTILINE))
01147 return;
01148 if (!es->text) {
01149 if (es->hloc)
01150 es->text = (char*)LocalLock(es->hloc);
01151 else {
01152
01153 return;
01154 }
01155 }
01156 es->lock_count++;
01157 }
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 static void EDIT_SL_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end)
01169 {
01170 RECT line_rect;
01171 RECT rc;
01172
01173 EDIT_GetLineRect(hwnd,0, es, 0, start, end, &line_rect);
01174
01175 if (IntersectRect(&rc, &line_rect, &es->format_rect))
01176 {
01177 HideCaret(hwnd);
01178 InvalidateRect(hwnd, &rc, TRUE);
01179 ShowCaret(hwnd);
01180 }
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 static void EDIT_ML_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end)
01193 {
01194 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
01195 INT sl = EDIT_EM_LineFromChar(hwnd, es, start);
01196 INT el = EDIT_EM_LineFromChar(hwnd, es, end);
01197 INT sc;
01198 INT ec;
01199 RECT rc1;
01200 RECT rcWnd;
01201 RECT rcLine;
01202 RECT rcUpdate;
01203 INT l;
01204
01205 if ((el < es->y_offset) || (sl > es->y_offset + vlc))
01206 return;
01207
01208 sc = start - EDIT_EM_LineIndex(hwnd, es, sl);
01209 ec = end - EDIT_EM_LineIndex(hwnd, es, el);
01210 if (sl < es->y_offset) {
01211 sl = es->y_offset;
01212 sc = 0;
01213 }
01214 if (el > es->y_offset + vlc) {
01215 el = es->y_offset + vlc;
01216 ec = EDIT_EM_LineLength(hwnd, es, EDIT_EM_LineIndex(hwnd, es, el));
01217 }
01218 GetClientRect(hwnd, &rc1);
01219 IntersectRect(&rcWnd, &rc1, &es->format_rect);
01220 HideCaret(hwnd);
01221 if (sl == el) {
01222 EDIT_GetLineRect(hwnd,0, es, sl, sc, ec, &rcLine);
01223
01224 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
01225 InvalidateRect(hwnd, &rcUpdate, TRUE);
01226 } else {
01227 EDIT_GetLineRect(hwnd,0, es, sl, sc,
01228 EDIT_EM_LineLength(hwnd, es,
01229 EDIT_EM_LineIndex(hwnd, es, sl)),
01230 &rcLine);
01231 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
01232 InvalidateRect(hwnd, &rcUpdate, TRUE);
01233 for (l = sl + 1 ; l < el ; l++) {
01234 EDIT_GetLineRect(hwnd,0, es, l, 0,
01235 EDIT_EM_LineLength(hwnd, es,
01236 EDIT_EM_LineIndex(hwnd, es, l)),
01237 &rcLine);
01238 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
01239 InvalidateRect(hwnd, &rcUpdate, TRUE);
01240 }
01241 EDIT_GetLineRect(hwnd,0, es, el, 0, ec, &rcLine);
01242 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
01243 InvalidateRect(hwnd, &rcUpdate, TRUE);
01244 }
01245 ShowCaret(hwnd);
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 static void EDIT_InvalidateText(HWND hwnd, EDITSTATE *es, INT start, INT end)
01261 {
01262 if (end == start)
01263 return;
01264
01265 if (end == -1)
01266 end = lstrlenA(es->text);
01267
01268 ORDER_INT(start, end);
01269
01270 if (es->style & ES_MULTILINE)
01271 EDIT_ML_InvalidateText(hwnd, es, start, end);
01272 else
01273 EDIT_SL_InvalidateText(hwnd, es, start, end);
01274 }
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284 static BOOL EDIT_MakeFit(HWND hwnd, EDITSTATE *es, INT size)
01285 {
01286 HLOCAL hNew32;
01287
01288 #ifndef __WIN32OS2__
01289 if (size > es->buffer_limit) {
01290 EDIT_NOTIFY_PARENT(hwnd, EN_MAXTEXT);
01291 return FALSE;
01292 }
01293 #endif
01294
01295 if (size <= es->buffer_size)
01296 return TRUE;
01297 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
01298
01299 #ifndef __WIN32OS2__
01300 if (size > es->buffer_limit)
01301 size = es->buffer_limit;
01302 #endif
01303
01304
01305
01306 EDIT_UnlockBuffer(hwnd, es, TRUE);
01307 if (es->text) {
01308 es->text = (char*)HeapReAlloc(es->heap, 0, es->text, size + 1);
01309 if (es->text)
01310 #ifdef __WIN32OS2__
01311 es->buffer_size = HeapSize(es->heap, 0, es->text) - 1;
01312 #else
01313 es->buffer_size = MIN(HeapSize(es->heap, 0, es->text) - 1, es->buffer_limit);
01314 #endif
01315 else
01316 es->buffer_size = 0;
01317 } else if (es->hloc) {
01318 hNew32 = LocalReAlloc(es->hloc, size + 1, 0);
01319 if (hNew32) {
01320
01321 es->hloc = hNew32;
01322 #ifdef __WIN32OS2__
01323 es->buffer_size = LocalSize(es->hloc) - 1;
01324 #else
01325 es->buffer_size = MIN(LocalSize(es->hloc) - 1, es->buffer_limit);
01326 #endif
01327 }
01328 }
01329 if (es->buffer_size < size) {
01330 EDIT_LockBuffer(hwnd, es);
01331
01332 EDIT_NOTIFY_PARENT(hwnd, EN_ERRSPACE);
01333 return FALSE;
01334 } else {
01335 EDIT_LockBuffer(hwnd, es);
01336
01337 return TRUE;
01338 }
01339 }
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 static BOOL EDIT_MakeUndoFit(HWND hwnd, EDITSTATE *es, INT size)
01350 {
01351 if (size <= es->undo_buffer_size)
01352 return TRUE;
01353 size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
01354
01355
01356 es->undo_text = (char*)HeapReAlloc(es->heap, 0, es->undo_text, size + 1);
01357 if (es->undo_text) {
01358 es->undo_buffer_size = HeapSize(es->heap, 0, es->undo_text) - 1;
01359 if (es->undo_buffer_size < size) {
01360
01361 return FALSE;
01362 }
01363 return TRUE;
01364 }
01365 return FALSE;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374 static void EDIT_MoveBackward(HWND hwnd, EDITSTATE *es, BOOL extend)
01375 {
01376 INT e = es->selection_end;
01377
01378 if (e) {
01379 e--;
01380 if ((es->style & ES_MULTILINE) && e &&
01381 (es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
01382 e--;
01383 if (e && (es->text[e - 1] == '\r'))
01384 e--;
01385 }
01386 }
01387 EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
01388 EDIT_EM_ScrollCaret(hwnd, es);
01389 }
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401 static void EDIT_MoveDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
01402 {
01403 INT s = es->selection_start;
01404 INT e = es->selection_end;
01405 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
01406 LRESULT pos = EDIT_EM_PosFromChar(hwnd,0, es, e, after_wrap);
01407 INT x = SLOWORD(pos);
01408 INT y = SHIWORD(pos);
01409
01410 e = EDIT_CharFromPos(hwnd, es, x, y + es->line_height, &after_wrap);
01411 if (!extend)
01412 s = e;
01413 EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
01414 EDIT_EM_ScrollCaret(hwnd, es);
01415 }
01416
01417
01418
01419
01420
01421
01422
01423 static void EDIT_MoveEnd(HWND hwnd, EDITSTATE *es, BOOL extend)
01424 {
01425 BOOL after_wrap = FALSE;
01426 INT e;
01427
01428
01429 if (es->style & ES_MULTILINE)
01430 e = EDIT_CharFromPos(hwnd, es, 0x3fffffff,
01431 HIWORD(EDIT_EM_PosFromChar(hwnd,0, es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
01432 else
01433 e = lstrlenA(es->text);
01434 EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, after_wrap);
01435 EDIT_EM_ScrollCaret(hwnd, es);
01436 }
01437
01438
01439
01440
01441
01442
01443
01444 static void EDIT_MoveForward(HWND hwnd, EDITSTATE *es, BOOL extend)
01445 {
01446 INT e = es->selection_end;
01447
01448 if (es->text[e]) {
01449 e++;
01450 if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
01451 if (es->text[e] == '\n')
01452 e++;
01453 else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
01454 e += 2;
01455 }
01456 }
01457 EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
01458 EDIT_EM_ScrollCaret(hwnd, es);
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 static void EDIT_MoveHome(HWND hwnd, EDITSTATE *es, BOOL extend)
01470 {
01471 INT e;
01472
01473
01474 if (es->style & ES_MULTILINE)
01475 e = EDIT_CharFromPos(hwnd, es, -es->x_offset,
01476 HIWORD(EDIT_EM_PosFromChar(hwnd,0, es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
01477 else
01478 e = 0;
01479 EDIT_EM_SetSel(hwnd, es, extend ? es->selection_start : e, e, FALSE);
01480 EDIT_EM_ScrollCaret(hwnd, es);
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493 static void EDIT_MovePageDown_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
01494 {
01495 INT s = es->selection_start;
01496 INT e = es->selection_end;
01497 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
01498 LRESULT pos = EDIT_EM_PosFromChar(hwnd,0, es, e, after_wrap);
01499 INT x = SLOWORD(pos);
01500 INT y = SHIWORD(pos);
01501
01502 e = EDIT_CharFromPos(hwnd, es, x,
01503 y + (es->format_rect.bottom - es->format_rect.top),
01504 &after_wrap);
01505 if (!extend)
01506 s = e;
01507 EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
01508 EDIT_EM_ScrollCaret(hwnd, es);
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 static void EDIT_MovePageUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
01522 {
01523 INT s = es->selection_start;
01524 INT e = es->selection_end;
01525 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
01526 LRESULT pos = EDIT_EM_PosFromChar(hwnd,0, es, e, after_wrap);
01527 INT x = SLOWORD(pos);
01528 INT y = SHIWORD(pos);
01529
01530 e = EDIT_CharFromPos(hwnd, es, x,
01531 y - (es->format_rect.bottom - es->format_rect.top),
01532 &after_wrap);
01533 if (!extend)
01534 s = e;
01535 EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
01536 EDIT_EM_ScrollCaret(hwnd, es);
01537 }
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 static void EDIT_MoveUp_ML(HWND hwnd, EDITSTATE *es, BOOL extend)
01550 {
01551 INT s = es->selection_start;
01552 INT e = es->selection_end;
01553 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
01554 LRESULT pos = EDIT_EM_PosFromChar(hwnd,0, es, e, after_wrap);
01555 INT x = SLOWORD(pos);
01556 INT y = SHIWORD(pos);
01557
01558 e = EDIT_CharFromPos(hwnd, es, x, y - es->line_height, &after_wrap);
01559 if (!extend)
01560 s = e;
01561 EDIT_EM_SetSel(hwnd, es, s, e, after_wrap);
01562 EDIT_EM_ScrollCaret(hwnd, es);
01563 }
01564
01565
01566
01567
01568
01569
01570
01571 static void EDIT_MoveWordBackward(HWND hwnd, EDITSTATE *es, BOOL extend)
01572 {
01573 INT s = es->selection_start;
01574 INT e = es->selection_end;
01575 INT l;
01576 INT ll;
01577 INT li;
01578
01579 l = EDIT_EM_LineFromChar(hwnd, es, e);
01580 ll = EDIT_EM_LineLength(hwnd, es, e);
01581 li = EDIT_EM_LineIndex(hwnd, es, l);
01582 if (e - li == 0) {
01583 if (l) {
01584 li = EDIT_EM_LineIndex(hwnd, es, l - 1);
01585 e = li + EDIT_EM_LineLength(hwnd, es, li);
01586 }
01587 } else {
01588 e = li + (INT)EDIT_CallWordBreakProc(hwnd, es,
01589 li, e - li, ll, WB_LEFT);
01590 }
01591 if (!extend)
01592 s = e;
01593 EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
01594 EDIT_EM_ScrollCaret(hwnd, es);
01595 }
01596
01597
01598
01599
01600
01601
01602
01603 static void EDIT_MoveWordForward(HWND hwnd, EDITSTATE *es, BOOL extend)
01604 {
01605 INT s = es->selection_start;
01606 INT e = es->selection_end;
01607 INT l;
01608 INT ll;
01609 INT li;
01610
01611 l = EDIT_EM_LineFromChar(hwnd, es, e);
01612 ll = EDIT_EM_LineLength(hwnd, es, e);
01613 li = EDIT_EM_LineIndex(hwnd, es, l);
01614 if (e - li == ll) {
01615 if ((es->style & ES_MULTILINE) && (l != es->line_count - 1))
01616 e = EDIT_EM_LineIndex(hwnd, es, l + 1);
01617 } else {
01618 e = li + EDIT_CallWordBreakProc(hwnd, es,
01619 li, e - li + 1, ll, WB_RIGHT);
01620 }
01621 if (!extend)
01622 s = e;
01623 EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
01624 EDIT_EM_ScrollCaret(hwnd, es);
01625 }
01626
01627
01628
01629
01630
01631
01632
01633 static void EDIT_PaintLine(HWND hwnd, EDITSTATE *es, HDC dc, INT line, BOOL rev)
01634 {
01635 INT s = es->selection_start;
01636 INT e = es->selection_end;
01637 INT li;
01638 INT ll;
01639 INT x;
01640 INT y;
01641 LRESULT pos;
01642
01643 if (es->style & ES_MULTILINE) {
01644 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
01645 if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count))
01646 return;
01647 } else if (line)
01648 return;
01649
01650
01651
01652 pos = EDIT_EM_PosFromChar(hwnd,dc, es, EDIT_EM_LineIndex(hwnd, es, line), FALSE);
01653 x = SLOWORD(pos);
01654 y = SHIWORD(pos);
01655 li = EDIT_EM_LineIndex(hwnd, es, line);
01656 ll = EDIT_EM_LineLength(hwnd, es, li);
01657 s = es->selection_start;
01658 e = es->selection_end;
01659 ORDER_INT(s, e);
01660 s = MIN(li + ll, MAX(li, s));
01661 e = MIN(li + ll, MAX(li, e));
01662
01663 if (rev && (s != e) && ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL)))
01664 {
01665 HRGN oldRgn,newRgn,combRgn;
01666 RECT rect;
01667
01668
01669
01670
01671 if (!(es->style & ES_MULTILINE))
01672 {
01673 SIZE size;
01674
01675 rect.top = y;
01676 rect.bottom = y+es->line_height;
01677 GetTextExtentPoint32A(dc,es->text+li,s-li,&size);
01678 rect.left = x+size.cx;
01679 GetTextExtentPoint32A(dc,es->text+li,e-li,&size);
01680 rect.right = x+size.cx;
01681
01682 oldRgn = CreateRectRgnIndirect(&rect);
01683 GetClipRgn(dc,oldRgn);
01684 newRgn = CreateRectRgnIndirect(&rect);
01685 combRgn = CreateRectRgnIndirect(&rect);
01686 CombineRgn(combRgn,oldRgn,newRgn,RGN_XOR);
01687 CombineRgn(combRgn,oldRgn,combRgn,RGN_AND);
01688 SelectClipRgn(dc,combRgn);
01689 EDIT_PaintText(hwnd,es,dc,x,y,line,0,ll,FALSE);
01690 CombineRgn(combRgn,oldRgn,newRgn,RGN_AND);
01691 SelectClipRgn(dc,combRgn);
01692 EDIT_PaintText(hwnd,es,dc,x,y,line,0,e-li,TRUE);
01693 DeleteObject(oldRgn);
01694 DeleteObject(newRgn);
01695 DeleteObject(combRgn);
01696 } else
01697 {
01698 rect.top = y;
01699 rect.bottom = y+es->line_height;
01700 rect.left = x+LOWORD(TabbedTextOutA(dc,x,y,es->text+li,s-li,es->tabs_count,es->tabs,es->format_rect.left-es->x_offset));
01701 rect.right = x+LOWORD(TabbedTextOutA(dc,x,y,es->text+li,e-li,es->tabs_count,es->tabs,es->format_rect.left-es->x_offset));
01702
01703 oldRgn = CreateRectRgnIndirect(&rect);
01704 GetClipRgn(dc,oldRgn);
01705 newRgn = CreateRectRgnIndirect(&rect);
01706 combRgn = CreateRectRgnIndirect(&rect);
01707 CombineRgn(combRgn,oldRgn,newRgn,RGN_XOR);
01708 CombineRgn(combRgn,oldRgn,combRgn,RGN_AND);
01709 SelectClipRgn(dc,combRgn);
01710 EDIT_PaintText(hwnd,es,dc,x,y,line,0,ll,FALSE);
01711 CombineRgn(combRgn,oldRgn,newRgn,RGN_AND);
01712 SelectClipRgn(dc,combRgn);
01713 EDIT_PaintText(hwnd,es,dc,x,y,line,0,e-li,TRUE);
01714 SelectClipRgn(dc,oldRgn);
01715 DeleteObject(oldRgn);
01716 DeleteObject(newRgn);
01717 DeleteObject(combRgn);
01718 }
01719 } else EDIT_PaintText(hwnd, es, dc, x, y, line, 0, ll, FALSE);
01720 }
01721
01722
01723
01724
01725
01726
01727
01728 static VOID EDIT_PaintText(HWND hwnd, EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col, INT count, BOOL rev)
01729 {
01730 COLORREF BkColor;
01731 COLORREF TextColor;
01732 INT li;
01733
01734 if (!count)
01735 return;
01736 BkColor = GetBkColor(dc);
01737 TextColor = GetTextColor(dc);
01738 if (rev)
01739 {
01740 SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT));
01741 SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT));
01742 }
01743 li = EDIT_EM_LineIndex(hwnd, es, line);
01744 if (es->style & ES_MULTILINE)
01745 {
01746 TabbedTextOutA(dc, x, y, es->text + li + col, count,
01747 es->tabs_count, es->tabs, es->format_rect.left - es->x_offset);
01748 } else
01749 {
01750 LPSTR text = EDIT_GetPasswordPointer_SL(hwnd, es);
01751 POINT pt;
01752
01753 TextOutA(dc,x,y,text+li+col,count);
01754 if (es->style & ES_PASSWORD)
01755 HeapFree(es->heap, 0, text);
01756 }
01757 if (rev)
01758 {
01759 SetBkColor(dc, BkColor);
01760 SetTextColor(dc, TextColor);
01761 }
01762 }
01763
01764
01765
01766
01767
01768
01769
01770 static void EDIT_SetCaretPos(HWND hwnd, EDITSTATE *es, INT pos,
01771 BOOL after_wrap)
01772 {
01773 LRESULT res = EDIT_EM_PosFromChar(hwnd,0, es, pos, after_wrap);
01774 INT x = SLOWORD(res);
01775 INT y = SHIWORD(res);
01776
01777 if(x < es->format_rect.left)
01778 x = es->format_rect.left;
01779 if(x > es->format_rect.right - 2)
01780 x = es->format_rect.right - 2;
01781 if(y > es->format_rect.bottom)
01782 y = es->format_rect.bottom;
01783 if(y < es->format_rect.top)
01784 y = es->format_rect.top;
01785 SetCaretPos(x, y);
01786 return;
01787 }
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798 static void EDIT_SetRectNP(HWND hwnd, EDITSTATE *es, LPRECT rc)
01799 {
01800 CopyRect(&es->format_rect, rc);
01801 if (es->style & WS_BORDER)
01802 {
01803 INT bw = GetSystemMetrics(SM_CXBORDER)+1,bh = GetSystemMetrics(SM_CYBORDER)+1;
01804
01805 es->format_rect.left += bw;
01806 es->format_rect.top += bh;
01807 es->format_rect.right -= bw;
01808 es->format_rect.bottom -= bh;
01809 }
01810 es->format_rect.left += es->left_margin;
01811 es->format_rect.right -= es->right_margin;
01812 es->format_rect.right = MAX(es->format_rect.right, es->format_rect.left + es->char_width);
01813 if (es->style & ES_MULTILINE)
01814 es->format_rect.bottom = es->format_rect.top +
01815 MAX(1, (es->format_rect.bottom - es->format_rect.top) / es->line_height) * es->line_height;
01816 else
01817 es->format_rect.bottom = es->format_rect.top + es->line_height;
01818 if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL))
01819 EDIT_BuildLineDefs_ML(hwnd,es);
01820 EDIT_UpdateScrollBars(hwnd,es,TRUE,TRUE);
01821 }
01822
01823
01824
01825
01826
01827
01828
01829 static void EDIT_UnlockBuffer(HWND hwnd, EDITSTATE *es, BOOL force)
01830 {
01831 if (!es) {
01832
01833 return;
01834 }
01835 if (!(es->style & ES_MULTILINE))
01836 return;
01837 if (!es->lock_count) {
01838
01839 return;
01840 }
01841 if (!es->text) {
01842
01843 return;
01844 }
01845 if (force || (es->lock_count == 1)) {
01846 if (es->hloc) {
01847 LocalUnlock(es->hloc);
01848 es->text = NULL;
01849 }
01850 }
01851 es->lock_count--;
01852 }
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 static INT EDIT_WordBreakProc(LPSTR s, INT index, INT count, INT action)
01867 {
01868 INT ret = 0;
01869
01870
01871
01872
01873 switch (action) {
01874 case WB_LEFT:
01875 if (!count)
01876 break;
01877 if (index)
01878 index--;
01879 if (s[index] == ' ') {
01880 while (index && (s[index] == ' '))
01881 index--;
01882 if (index) {
01883 while (index && (s[index] != ' '))
01884 index--;
01885 if (s[index] == ' ')
01886 index++;
01887 }
01888 } else {
01889 while (index && (s[index] != ' '))
01890 index--;
01891 if (s[index] == ' ')
01892 index++;
01893 }
01894 ret = index;
01895 break;
01896 case WB_RIGHT:
01897 if (!count)
01898 break;
01899 if (index)
01900 index--;
01901 if (s[index] == ' ')
01902 while ((index < count) && (s[index] == ' ')) index++;
01903 else {
01904 while (s[index] && (s[index] != ' ') && (index < count))
01905 index++;
01906 while ((s[index] == ' ') && (index < count)) index++;
01907 }
01908 ret = index;
01909 break;
01910 case WB_ISDELIMITER:
01911 ret = (s[index] == ' ');
01912 break;
01913 default:
01914
01915 break;
01916 }
01917 return ret;
01918 }
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930 static LRESULT EDIT_EM_CharFromPos(HWND hwnd, EDITSTATE *es, INT x, INT y)
01931 {
01932 POINT pt;
01933 INT index;
01934
01935 pt.x = x;
01936 pt.y = y;
01937
01938 if (!PtInRect(&es->format_rect,pt)) return -1;
01939
01940 index = EDIT_CharFromPos(hwnd, es, x, y, NULL);
01941 return MAKELONG(index, EDIT_EM_LineFromChar(hwnd, es, index));
01942 }
01943
01944
01945
01946
01947
01948
01949
01950
01951 static BOOL EDIT_EM_FmtLines(HWND hwnd, EDITSTATE *es, BOOL add_eol)
01952 {
01953 es->flags &= ~EF_USE_SOFTBRK;
01954 if (add_eol) {
01955 es->flags |= EF_USE_SOFTBRK;
01956 dprintf(("EDIT: EM_FMTLINES: soft break enabled, not implemented\n"));
01957 }
01958 return add_eol;
01959 }
01960
01961 static INT EDIT_EM_GetFirstVisibleLine(HWND hwnd,EDITSTATE *es)
01962 {
01963 return (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
01964 }
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982 static HLOCAL EDIT_EM_GetHandle(HWND hwnd, EDITSTATE *es)
01983 {
01984 HLOCAL newBuf;
01985 LPSTR newText;
01986 INT newSize;
01987
01988 if (!(es->style & ES_MULTILINE))
01989 return 0;
01990
01991 if (es->hloc)
01992 return es->hloc;
01993
01994 if (!(newBuf = LocalAlloc(LMEM_MOVEABLE, lstrlenA(es->text) + 1))) {
01995
01996 return 0;
01997 }
01998 #ifdef __WIN32OS2__
01999 newSize = LocalSize(newBuf) - 1;
02000 #else
02001 newSize = MIN(LocalSize(newBuf) - 1, es->buffer_limit);
02002 #endif
02003 if (!(newText = (char*)LocalLock(newBuf))) {
02004
02005 LocalFree(newBuf);
02006 return 0;
02007 }
02008 lstrcpyA(newText, es->text);
02009 EDIT_UnlockBuffer(hwnd, es, TRUE);
02010 if (es->text)
02011 HeapFree(es->heap, 0, es->text);
02012 es->hloc = newBuf;
02013 es->buffer_size = newSize;
02014 es->text = newText;
02015 EDIT_LockBuffer(hwnd, es);
02016
02017
02018 return es->hloc;
02019 }
02020
02021 static INT EDIT_EM_GetLimitText(HWND hwnd,EDITSTATE *es)
02022 {
02023 return es->buffer_limit;
02024 }
02025
02026
02027
02028
02029
02030
02031 static INT EDIT_EM_GetLine(HWND hwnd, EDITSTATE *es, INT line, LPSTR lpch)
02032 {
02033 LPSTR src;
02034 INT len;
02035 INT i;
02036
02037 if (!lpch || (*(WORD*)lpch == 0)) return 0;
02038
02039 if (es->style & ES_MULTILINE) {
02040 if (line >= es->line_count)
02041 return 0;
02042 } else
02043 line = 0;
02044 i = EDIT_EM_LineIndex(hwnd, es, line);
02045 src = es->text + i;
02046 len = MIN(*(WORD *)lpch, EDIT_EM_LineLength(hwnd, es, i));
02047 for (i = 0 ; i < len ; i++) {
02048 *lpch = *src;
02049 src++;
02050 lpch++;
02051 }
02052
02053 *lpch = 0;
02054 return (LRESULT)len;
02055 }
02056
02057 static INT EDIT_EM_GetLineCount(HWND hwnd,EDITSTATE *es)
02058 {
02059 return (es->style & ES_MULTILINE) ? es->line_count : 1;
02060 }
02061
02062 static LONG EDIT_EM_GetMargins(HWND hwnd,EDITSTATE *es)
02063 {
02064 return MAKELONG(es->left_margin, es->right_margin);
02065 }
02066
02067 static BOOL EDIT_EM_GetModify(HWND hwnd,EDITSTATE *es)
02068 {
02069 return ((es->flags & EF_MODIFIED) != 0);
02070 }
02071
02072 static CHAR EDIT_EM_GetPasswordChar(HWND hwnd,EDITSTATE *es)
02073 {
02074 return es->password_char;
02075 }
02076
02077 static VOID EDIT_EM_GetRect(HWND hwnd,EDITSTATE *es,LPRECT lprc)
02078 {
02079 if (lprc) CopyRect(lprc,&es->format_rect);
02080 }
02081
02082
02083
02084
02085
02086
02087 static LRESULT EDIT_EM_GetSel(HWND hwnd, EDITSTATE *es, LPUINT start, LPUINT end)
02088 {
02089 UINT s = es->selection_start;
02090 UINT e = es->selection_end;
02091
02092 ORDER_UINT(s, e);
02093
02094 if (start)
02095 *start = s;
02096 if (end)
02097 *end = e;
02098 return MAKELONG(s, e);
02099 }
02100
02101
02102
02103
02104
02105 static LRESULT EDIT_EM_GetThumb(HWND hwnd, EDITSTATE *es)
02106 {
02107 SCROLLINFO si;
02108
02109 if (!(es->style & ES_MULTILINE)) return 0;
02110
02111 si.cbSize = sizeof(si);
02112 si.fMask = SIF_TRACKPOS;
02113 return GetScrollInfo(hwnd,SB_VERT,&si) ? si.nTrackPos:0;
02114 }
02115
02116 static PVOID EDIT_EM_GetWordbreakProc(HWND hwnd,EDITSTATE *es)
02117 {
02118 return es->word_break_procA;
02119 }
02120
02121
02122
02123
02124
02125
02126 static INT EDIT_EM_LineFromChar(HWND hwnd, EDITSTATE *es, INT index)
02127 {
02128 INT line;
02129 LINEDEF *line_def;
02130
02131 if (!(es->style & ES_MULTILINE))
02132 return 0;
02133 if (index > lstrlenA(es->text))
02134 return es->line_count - 1;
02135 if (index == -1)
02136 index = MIN(es->selection_start, es->selection_end);
02137
02138 line = 0;
02139 line_def = es->first_line_def;
02140 index -= line_def->length;
02141 while ((index >= 0) && line_def->next) {
02142 line++;
02143 line_def = line_def->next;
02144 index -= line_def->length;
02145 }
02146 return line;
02147 }
02148
02149
02150
02151
02152
02153
02154
02155 static INT EDIT_EM_LineIndex(HWND hwnd, EDITSTATE *es, INT line)
02156 {
02157 INT line_index;
02158 LINEDEF *line_def;
02159
02160 if (!(es->style & ES_MULTILINE))
02161 return 0;
02162 if (line >= es->line_count)
02163 return -1;
02164
02165 line_index = 0;
02166 line_def = es->first_line_def;
02167 if (line == -1) {
02168 INT index = es->selection_end - line_def->length;
02169 while ((index >= 0) && line_def->next) {
02170 line_index += line_def->length;
02171 line_def = line_def->next;
02172 index -= line_def->length;
02173 }
02174 } else {
02175 while (line > 0) {
02176 line_index += line_def->length;
02177 line_def = line_def->next;
02178 line--;
02179 }
02180 }
02181 return line_index;
02182 }
02183
02184
02185
02186
02187
02188
02189
02190 static INT EDIT_EM_LineLength(HWND hwnd, EDITSTATE *es, INT index)
02191 {
02192 LINEDEF *line_def;
02193
02194 if (!(es->style & ES_MULTILINE))
02195 return lstrlenA(es->text);
02196
02197 if (index == -1)
02198 {
02199 INT sl = EDIT_EM_LineFromChar(hwnd,es,MIN(es->selection_start,es->selection_end));
02200 INT el = EDIT_EM_LineFromChar(hwnd,es,MAX(es->selection_start,es->selection_end));
02201
02202 if (sl == el)
02203 return EDIT_EM_LineLength(hwnd,es,sl)+es->selection_start-es->selection_end;
02204 else
02205 return es->selection_start+EDIT_EM_LineLength(hwnd,es,el)-es->selection_end;
02206 }
02207 line_def = es->first_line_def;
02208 index -= line_def->length;
02209 while ((index >= 0) && line_def->next) {
02210 line_def = line_def->next;
02211 index -= line_def->length;
02212 }
02213 return line_def->net_length;
02214 }
02215
02216 static VOID EDIT_UpdateScrollBars(HWND hwnd,EDITSTATE *es,BOOL updateHorz,BOOL updateVert)
02217 {
02218 if (updateHorz && (es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
02219 {
02220 SCROLLINFO si;
02221 INT fw = es->format_rect.right - es->format_rect.left;
02222
02223 si.cbSize = sizeof(SCROLLINFO);
02224 si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
02225 si.nMin = 0;
02226 si.nMax = es->text_width + fw - 1;
02227 si.nPage = fw;
02228 si.nPos = es->x_offset;
02229 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
02230 }
02231
02232 if (updateVert && (es->style & WS_VSCROLL) && !(es->flags & EF_VSCROLL_TRACK))
02233 {
02234 INT vlc = (es->format_rect.bottom-es->format_rect.top)/es->line_height;
02235 SCROLLINFO si;
02236
02237 si.cbSize = sizeof(SCROLLINFO);
02238 si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
02239 si.nMin = 0;
02240 si.nMax = es->line_count + vlc - 2;
02241 si.nPage = vlc;
02242 si.nPos = es->y_offset;
02243 SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
02244 }
02245 }
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257 static BOOL EDIT_EM_LineScroll(HWND hwnd, EDITSTATE *es, INT dx, INT dy)
02258 {
02259 INT nyoff;
02260 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
02261
02262 if (!(es->style & ES_MULTILINE))
02263 return FALSE;
02264
02265 if (-dx > es->x_offset)
02266 dx = -es->x_offset;
02267 if (dx > es->text_width - es->x_offset)
02268 dx = es->text_width - es->x_offset;
02269 nyoff = MAX(0, es->y_offset + dy);
02270
02271
02272
02273
02274
02275 if (nyoff >= es->line_count) {
02276 if(es->line_count <= vlc) {
02277 nyoff = es->y_offset;
02278 }
02279 else nyoff = es->line_count - vlc - 1;
02280 }
02281 dy = (es->y_offset - nyoff) * es->line_height;
02282 if (dx || dy)
02283 {
02284 RECT rc1;
02285 RECT rc;
02286
02287 if (dx && !(es->flags & EF_HSCROLL_TRACK))
02288 EDIT_NOTIFY_PARENT(hwnd, EN_HSCROLL);
02289 if (dy && !(es->flags & EF_VSCROLL_TRACK))
02290 EDIT_NOTIFY_PARENT(hwnd, EN_VSCROLL);
02291
02292 GetClientRect(hwnd, &rc1);
02293 IntersectRect(&rc, &rc1, &es->format_rect);
02294
02295 ScrollWindowEx(hwnd,-dx,dy,NULL,&rc,(HRGN)NULL,NULL,SW_INVALIDATE);
02296 es->y_offset = nyoff;
02297 es->x_offset += dx;
02298 EDIT_UpdateScrollBars(hwnd,es,dx,dy);
02299 }
02300
02301 return TRUE;
02302 }
02303
02304
02305
02306
02307
02308
02309
02310 static LRESULT EDIT_EM_PosFromChar(HWND hwnd,HDC dc, EDITSTATE *es, INT index, BOOL after_wrap)
02311 {
02312 INT len = lstrlenA(es->text);
02313 INT l;
02314 INT li;
02315 INT x;
02316 INT y = 0;
02317 BOOL createdDC = FALSE;
02318 HFONT old_font = 0;
02319 SIZE size;
02320
02321 index = MIN(index, len);
02322 if (!dc)
02323 {
02324 dc = GetDC(hwnd);
02325 if (es->font)
02326 old_font = SelectObject(dc, es->font);
02327 createdDC = TRUE;
02328 }
02329 if (es->style & ES_MULTILINE) {
02330 l = EDIT_EM_LineFromChar(hwnd, es, index);
02331 y = (l - es->y_offset) * es->line_height;
02332 li = EDIT_EM_LineIndex(hwnd, es, l);
02333 if (after_wrap && (li == index) && l) {
02334 INT l2 = l - 1;
02335 LINEDEF *line_def = es->first_line_def;
02336 while (l2) {
02337 line_def = line_def->next;
02338 l2--;
02339 }
02340 if (line_def->ending == END_WRAP) {
02341 l--;
02342 y -= es->line_height;
02343 li = EDIT_EM_LineIndex(hwnd, es, l);
02344 }
02345 }
02346 x = LOWORD(GetTabbedTextExtentA(dc, es->text + li, index - li,
02347 es->tabs_count, es->tabs)) - es->x_offset;
02348 } else
02349 {
02350 LPSTR text = EDIT_GetPasswordPointer_SL(hwnd, es);
02351
02352 GetTextExtentPoint32A(dc,text,index,&size);
02353 x = size.cx;
02354 if (es->x_offset)
02355 {
02356 GetTextExtentPoint32A(dc,text,es->x_offset,&size);
02357 x -= size.cx;
02358 }
02359 y = 0;
02360 if (es->style & ES_PASSWORD)
02361 HeapFree(es->heap, 0 ,text);
02362 }
02363 x += es->format_rect.left;
02364 y += es->format_rect.top;
02365 if (createdDC)
02366 {
02367 if (es->font)
02368 SelectObject(dc, old_font);
02369 ReleaseDC(hwnd, dc);
02370 }
02371 return MAKELONG((INT16)x, (INT16)y);
02372 }
02373
02374 BOOL EDIT_CheckNumber(CHAR *text)
02375 {
02376 if (!text) return TRUE;
02377
02378 while (text[0] != 0)
02379 {
02380 if ((BYTE)text[0] < '0' || (BYTE)text[0] > '9') return FALSE;
02381 text++;
02382 }
02383
02384 return TRUE;
02385 }
02386
02387
02388
02389
02390
02391
02392 static void EDIT_EM_ReplaceSel(HWND hwnd, EDITSTATE *es, BOOL can_undo, LPCSTR lpsz_replace)
02393 {
02394 INT strl = lstrlenA(lpsz_replace);
02395 INT tl = lstrlenA(es->text);
02396 INT utl;
02397 UINT s;
02398 UINT e;
02399 INT i;
02400 LPSTR p;
02401
02402 s = es->selection_start;
02403 e = es->selection_end;
02404
02405 if ((s == e) && !strl)
02406 return;
02407
02408 ORDER_UINT(s, e);
02409
02410 if (!EDIT_MakeFit(hwnd, es, tl - (e - s) + strl))
02411 return;
02412
02413 if (e != s) {
02414
02415 if (can_undo) {
02416 utl = lstrlenA(es->undo_text);
02417 if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
02418
02419 EDIT_MakeUndoFit(hwnd, es, utl + e - s);
02420 lstrcpynA(es->undo_text + utl, es->text + s, e - s + 1);
02421 } else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
02422
02423 EDIT_MakeUndoFit(hwnd, es, utl + e - s);
02424 for (p = es->undo_text + utl ; p >= es->undo_text ; p--)
02425 p[e - s] = p[0];
02426 for (i = 0 , p = es->undo_text ; i < e - s ; i++)
02427 p[i] = (es->text + s)[i];
02428 es->undo_position = s;
02429 } else {
02430
02431 EDIT_MakeUndoFit(hwnd, es, e - s);
02432 lstrcpynA(es->undo_text, es->text + s, e - s + 1);
02433 es->undo_position = s;
02434 }
02435
02436 es->undo_insert_count = 0;
02437 } else
02438 EDIT_EM_EmptyUndoBuffer(hwnd, es);
02439
02440
02441 lstrcpyA(es->text + s, es->text + e);
02442 }
02443 if (strl)
02444 {
02445 if ((es->style & ES_NUMBER) && !EDIT_CheckNumber((CHAR*)lpsz_replace))
02446 MessageBeep(MB_ICONEXCLAMATION);
02447 else
02448 {
02449
02450 if (can_undo) {
02451 if ((s == es->undo_position) ||
02452 ((es->undo_insert_count) &&
02453 (s == es->undo_position + es->undo_insert_count)))
02454
02455
02456
02457
02458 es->undo_insert_count += strl;
02459 else {
02460
02461 es->undo_position = s;
02462 es->undo_insert_count = strl;
02463
02464 *es->undo_text = '\0';
02465 }
02466 } else
02467 EDIT_EM_EmptyUndoBuffer(hwnd, es);
02468
02469
02470
02471 tl = lstrlenA(es->text);
02472 for (p = es->text + tl ; p >= es->text + s ; p--)
02473 p[strl] = p[0];
02474 for (i = 0 , p = es->text + s ; i < strl ; i++)
02475 p[i] = lpsz_replace[i];
02476
02477 if (es->style & ES_OEMCONVERT)
02478 {
02479 CHAR *text = (LPSTR)HeapAlloc(es->heap,0,strl);
02480
02481 CharToOemBuffA(lpsz_replace,text,strl);
02482 OemToCharBuffA(text,p,strl);
02483 HeapFree(es->heap,0,text);
02484 }
02485
02486 if(es->style & ES_UPPERCASE)
02487 CharUpperBuffA(p, strl);
02488 else if(es->style & ES_LOWERCASE)
02489 CharLowerBuffA(p, strl);
02490
02491 s += strl;
02492 }
02493 }
02494
02495 if (es->style & ES_MULTILINE)
02496 EDIT_BuildLineDefs_ML(hwnd,es);
02497
02498 EDIT_EM_SetSel(hwnd, es, s, s, FALSE);
02499
02500 es->flags |= EF_MODIFIED;
02501 es->flags |= EF_UPDATE;
02502 EDIT_EM_ScrollCaret(hwnd, es);
02503
02504
02505 EDIT_Refresh(hwnd,es,TRUE);
02506 }
02507
02508
02509
02510
02511
02512
02513
02514 static LRESULT EDIT_EM_Scroll(HWND hwnd, EDITSTATE *es, INT action)
02515 {
02516 INT dy;
02517
02518 if (!(es->style & ES_MULTILINE))
02519 return (LRESULT)FALSE;
02520
02521 dy = 0;
02522
02523 switch (action) {
02524 case SB_LINEUP:
02525 if (es->y_offset)
02526 dy = -1;
02527 break;
02528 case SB_LINEDOWN:
02529 if (es->y_offset < es->line_count - 1)
02530 dy = 1;
02531 break;
02532 case SB_PAGEUP:
02533 if (es->y_offset)
02534 dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
02535 break;
02536 case SB_PAGEDOWN:
02537 if (es->y_offset < es->line_count - 1)
02538 dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
02539 break;
02540 default:
02541 return (LRESULT)FALSE;
02542 }
02543 if (dy) {
02544 EDIT_NOTIFY_PARENT(hwnd, EN_VSCROLL);
02545 EDIT_EM_LineScroll(hwnd, es, 0, dy);
02546 }
02547 return MAKELONG((INT16)dy, (BOOL16)TRUE);
02548 }
02549
02550
02551
02552
02553
02554
02555
02556 static void EDIT_EM_ScrollCaret(HWND hwnd, EDITSTATE *es)
02557 {
02558 if (es->style & ES_MULTILINE) {
02559 INT l;
02560 INT li;
02561 INT vlc;
02562 INT ww;
02563 INT cw = es->char_width;
02564 INT x;
02565 INT dy = 0;
02566 INT dx = 0;
02567
02568 l = EDIT_EM_LineFromChar(hwnd, es, es->selection_end);
02569 li = EDIT_EM_LineIndex(hwnd, es, l);
02570 x = SLOWORD(EDIT_EM_PosFromChar(hwnd,0, es, es->selection_end, es->flags & EF_AFTER_WRAP));
02571 vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
02572 if (l >= es->y_offset + vlc)
02573 dy = l - vlc + 1 - es->y_offset;
02574 if (l < es->y_offset)
02575 dy = l - es->y_offset;
02576 ww = es->format_rect.right - es->format_rect.left;
02577 if (x < es->format_rect.left)
02578 dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
02579 if (x > es->format_rect.right)
02580 dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
02581 if (dy || dx)
02582 EDIT_EM_LineScroll(hwnd, es, dx, dy);
02583 } else {
02584 INT x;
02585 INT goal;
02586 INT format_width;
02587
02588 if (!(es->style & ES_AUTOHSCROLL))
02589 return;
02590
02591 x = SLOWORD(EDIT_EM_PosFromChar(hwnd,0, es, es->selection_end, FALSE));
02592 format_width = es->format_rect.right - es->format_rect.left;
02593 if (x < es->format_rect.left)
02594 {
02595 goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
02596 do {
02597 es->x_offset--;
02598 x = SLOWORD(EDIT_EM_PosFromChar(hwnd,0, es, es->selection_end, FALSE));
02599 } while ((x < goal) && es->x_offset);
02600
02601 EDIT_Refresh(hwnd,es,TRUE);
02602 EDIT_UpdateScrollBars(hwnd,es,TRUE,FALSE);
02603 } else if (x > es->format_rect.right)
02604 {
02605 INT x_last;
02606 INT len = lstrlenA(es->text);
02607 goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
02608 do {
02609 es->x_offset++;
02610 x = SLOWORD(EDIT_EM_PosFromChar(hwnd,0, es, es->selection_end, FALSE));
02611 x_last = SLOWORD(EDIT_EM_PosFromChar(hwnd,0, es, len, FALSE));
02612 } while ((x > goal) && (x_last > es->format_rect.right));
02613
02614 EDIT_Refresh(hwnd,es,TRUE);
02615 EDIT_UpdateScrollBars(hwnd,es,TRUE,FALSE);
02616 }
02617 }
02618 }
02619
02620
02621
02622
02623
02624
02625
02626 static void EDIT_EM_SetHandle(HWND hwnd, EDITSTATE *es, HLOCAL hloc)
02627 {
02628 if (!(es->style & ES_MULTILINE))
02629 return;
02630
02631 if (!hloc) {
02632
02633 return;
02634 }
02635
02636 EDIT_UnlockBuffer(hwnd, es, TRUE);
02637
02638
02639
02640
02641
02642 if (es->text)
02643 HeapFree(es->heap, 0, es->text);
02644
02645 es->hloc = hloc;
02646 es->text = NULL;
02647 es->buffer_size = LocalSize(es->hloc) - 1;
02648 EDIT_LockBuffer(hwnd, es);
02649
02650 if (es->text && (es->text[0] != 0))
02651 {
02652 if (es->style & ES_NUMBER)
02653 {
02654
02655 }
02656
02657 if (es->style & ES_OEMCONVERT)
02658 {
02659 INT len = lstrlenA(es->text);
02660 CHAR *text = (LPSTR)HeapAlloc(es->heap,0,len);
02661
02662 CharToOemBuffA(es->text,text,len);
02663 OemToCharBuffA(text,es->text,len);
02664 HeapFree(es->heap,0,text);
02665 }
02666
02667 if(es->style & ES_UPPERCASE)
02668 CharUpperA(es->text);
02669 else if(es->style & ES_LOWERCASE)
02670 CharLowerA(es->text);
02671 }
02672
02673 es->x_offset = es->y_offset = 0;
02674 es->selection_start = es->selection_end = 0;
02675 EDIT_EM_EmptyUndoBuffer(hwnd, es);
02676 es->flags &= ~EF_MODIFIED;
02677 es->flags &= ~EF_UPDATE;
02678 EDIT_BuildLineDefs_ML(hwnd,es);
02679 EDIT_Refresh(hwnd,es,FALSE);
02680 EDIT_EM_ScrollCaret(hwnd, es);
02681 EDIT_UpdateScrollBars(hwnd,es,TRUE,TRUE);
02682 }
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692 static void EDIT_EM_SetLimitText(HWND hwnd, EDITSTATE *es, INT limit)
02693 {
02694 if (es->style & ES_MULTILINE) {
02695 if (limit)
02696 #ifdef __WIN32OS2__
02697 es->buffer_limit = limit;
02698 #else
02699 es->buffer_limit = MIN(limit, BUFLIMIT_MULTI);
02700 #endif
02701 else
02702 es->buffer_limit = BUFLIMIT_MULTI;
02703 } else {
02704 if (limit)
02705 #ifdef __WIN32OS2__
02706 es->buffer_limit = MIN(limit, BUFLIMIT_SINGLE_NT);
02707 #else
02708 es->buffer_limit = MIN(limit, BUFLIMIT_SINGLE);
02709 #endif
02710 else
02711 es->buffer_limit = BUFLIMIT_SINGLE;
02712 }
02713 }
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725 static void EDIT_EM_SetMargins(HWND hwnd, EDITSTATE *es, INT action,
02726 INT left, INT right)
02727 {
02728 RECT r;
02729 INT oldLeft = es->left_margin,oldRight = es->right_margin;
02730
02731 if (action & EC_LEFTMARGIN) {
02732 if (left != EC_USEFONTINFO)
02733 es->left_margin = left;
02734 else
02735 es->left_margin = es->char_width / 3;
02736 }
02737
02738 if (action & EC_RIGHTMARGIN) {
02739 if (right != EC_USEFONTINFO)
02740 es->right_margin = right;
02741 else
02742 es->right_margin = es->char_width / 3;
02743 }
02744
02745
02746 if ((oldLeft != es->left_margin) || (oldRight != es->right_margin))
02747 {
02748 GetClientRect(hwnd, &r);
02749 EDIT_SetRectNP(hwnd, es, &r);
02750 if (es->style & ES_MULTILINE)
02751 EDIT_BuildLineDefs_ML(hwnd,es);
02752
02753 EDIT_Refresh(hwnd,es,FALSE);
02754 if (es->flags & EF_FOCUSED) {
02755 DestroyCaret();
02756 CreateCaret(hwnd, 0, 2, es->line_height);
02757 EDIT_SetCaretPos(hwnd, es, es->selection_end,
02758 es->flags & EF_AFTER_WRAP);
02759 ShowCaret(hwnd);
02760 }
02761 }
02762 }
02763
02764 static void EDIT_EM_SetModify(HWND hwnd,EDITSTATE *es,BOOL fModified)
02765 {
02766 if (fModified)
02767 es->flags |= EF_MODIFIED;
02768 else
02769 es->flags &= ~(EF_MODIFIED | EF_UPDATE);
02770 }
02771
02772
02773
02774
02775
02776
02777 static void EDIT_EM_SetPasswordChar(HWND hwnd, EDITSTATE *es, CHAR c)
02778 {
02779 if (es->style & ES_MULTILINE)
02780 return;
02781
02782 if (es->password_char == c)
02783 return;
02784
02785 es->password_char = c;
02786 if (c) {
02787 SetWindowLongA(hwnd,GWL_STYLE,GetWindowLongA(hwnd,GWL_STYLE) | ES_PASSWORD);
02788 es->style |= ES_PASSWORD;
02789 } else {
02790 SetWindowLongA(hwnd,GWL_STYLE,GetWindowLongA(hwnd,GWL_STYLE) & ~ES_PASSWORD);
02791 es->style &= ~ES_PASSWORD;
02792 }
02793 EDIT_Refresh(hwnd,es,FALSE);
02794 }
02795
02796 static BOOL EDIT_EM_SetReadOnly(HWND hwnd,EDITSTATE *es,BOOL fReadOnly)
02797 {
02798 if (fReadOnly)
02799 {
02800 SetWindowLongA(hwnd,GWL_STYLE,GetWindowLongA(hwnd,GWL_STYLE) | ES_READONLY);
02801 es->style |= ES_READONLY;
02802 } else
02803 {
02804 SetWindowLongA(hwnd,GWL_STYLE,GetWindowLongA(hwnd,GWL_STYLE) & ~ES_READONLY);
02805 es->style &= ~ES_READONLY;
02806 }
02807
02808 return TRUE;
02809 }
02810
02811 static void EDIT_EM_SetRect(HWND hwnd,EDITSTATE *es,LPRECT lprc)
02812 {
02813 if ((es->style & ES_MULTILINE) && lprc)
02814 {
02815 EDIT_SetRectNP(hwnd,es,lprc);
02816 EDIT_Refresh(hwnd,es,FALSE);
02817 }
02818 }
02819
02820 static void EDIT_EM_SetRectNP(HWND hwnd,EDITSTATE *es,LPRECT lprc)
02821 {
02822 if ((es->style & ES_MULTILINE) && lprc)
02823 EDIT_SetRectNP(hwnd,es,lprc);
02824 }
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835 static void EDIT_EM_SetSel(HWND hwnd, EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
02836 {
02837 UINT old_start = es->selection_start;
02838 UINT old_end = es->selection_end;
02839 UINT len = lstrlenA(es->text);
02840
02841 if (start == -1) {
02842 start = es->selection_end;
02843 end = es->selection_end;
02844 } else {
02845 start = MIN(start, len);
02846 end = MIN(end, len);
02847 }
02848 es->selection_start = start;
02849 es->selection_end = end;
02850 if (after_wrap)
02851 es->flags |= EF_AFTER_WRAP;
02852 else
02853 es->flags &= ~EF_AFTER_WRAP;
02854 if (es->flags & EF_FOCUSED)
02855 EDIT_SetCaretPos(hwnd, es, end, after_wrap);
02856
02857 ORDER_UINT(start, end);
02858 ORDER_UINT(end, old_end);
02859 ORDER_UINT(start, old_start);
02860 ORDER_UINT(old_start, old_end);
02861 if ((start == old_start) && (end == old_end)) return;
02862 if (end != old_start)
02863 {
02864
02865
02866
02867
02868
02869
02870
02871 if (old_start > end )
02872 {
02873 EDIT_InvalidateText(hwnd, es, start, end);
02874 EDIT_InvalidateText(hwnd, es, old_start, old_end);
02875 }
02876 else
02877 {
02878 EDIT_InvalidateText(hwnd, es, start, old_start);
02879 EDIT_InvalidateText(hwnd, es, end, old_end);
02880 }
02881 }
02882 else EDIT_InvalidateText(hwnd, es, start, old_end);
02883 }
02884
02885
02886
02887
02888
02889
02890
02891 static BOOL EDIT_EM_SetTabStops(HWND hwnd, EDITSTATE *es, INT count, LPINT tabs)
02892 {
02893 if (!(es->style & ES_MULTILINE))
02894 return FALSE;
02895 if (es->tabs)
02896 HeapFree(es->heap, 0, es->tabs);
02897 es->tabs_count = count;
02898 if (!count)
02899 es->tabs = NULL;
02900 else {
02901 es->tabs = (INT*)HeapAlloc(es->heap, 0, count * sizeof(INT));
02902 memcpy(es->tabs, tabs, count * sizeof(INT));
02903 }
02904 return TRUE;
02905 }
02906
02907
02908
02909
02910
02911
02912
02913 static void EDIT_EM_SetWordBreakProc(HWND hwnd, EDITSTATE *es, EDITWORDBREAKPROCA wbp)
02914 {
02915 if (es->word_break_procA == wbp)
02916 return;
02917
02918 es->word_break_procA = wbp;
02919 if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
02920 EDIT_BuildLineDefs_ML(hwnd,es);
02921 EDIT_Refresh(hwnd,es,FALSE);
02922 }
02923 }
02924
02925
02926
02927
02928
02929
02930
02931 static BOOL EDIT_EM_Undo(HWND hwnd, EDITSTATE *es)
02932 {
02933 INT ulength = lstrlenA(es->undo_text);
02934 LPSTR utext = (LPSTR)HeapAlloc(es->heap, 0, ulength + 1);
02935
02936 lstrcpyA(utext, es->undo_text);
02937
02938
02939
02940
02941 EDIT_EM_SetSel(hwnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
02942 EDIT_EM_EmptyUndoBuffer(hwnd, es);
02943 EDIT_EM_ReplaceSel(hwnd, es, TRUE, utext);
02944 EDIT_EM_SetSel(hwnd, es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
02945 HeapFree(es->heap, 0, utext);
02946
02947
02948
02949
02950 if (es->flags & EF_UPDATE) {
02951 es->flags &= ~EF_UPDATE;
02952 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
02953 }
02954
02955 return TRUE;
02956 }
02957
02958 static LRESULT EDIT_EM_SetIMEStatus(HWND hwnd,EDITSTATE *es,WPARAM wParam,LPARAM lParam)
02959 {
02960 if (wParam == EMSIS_COMPOSITIONSTRING)
02961 {
02962
02963 }
02964
02965 return 0;
02966 }
02967
02968 static LRESULT EDIT_EM_GetIMEStatus(HWND hwnd,EDITSTATE *es,WPARAM wParam,LPARAM lParam)
02969 {
02970
02971
02972 return 0;
02973 }
02974
02975
02976
02977
02978
02979
02980 static void EDIT_WM_Char(HWND hwnd, EDITSTATE *es, CHAR c, DWORD key_data)
02981 {
02982 BOOL control = GetKeyState(VK_CONTROL) & 0x8000;
02983 switch (c) {
02984 case '\r':
02985
02986 if(!(es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN))
02987 {
02988 MessageBeep(MB_ICONEXCLAMATION);
02989 break;
02990 }
02991 case '\n':
02992 if (es->style & ES_MULTILINE) {
02993 if (es->style & ES_READONLY) {
02994 EDIT_MoveHome(hwnd, es, FALSE);
02995 EDIT_MoveDown_ML(hwnd, es, FALSE);
02996 } else
02997 {
02998 EDIT_EM_ReplaceSel(hwnd, es, TRUE, "\r\n");
02999 if (es->flags & EF_UPDATE) {
03000 es->flags &= ~EF_UPDATE;
03001 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
03002 }
03003 }
03004 }
03005 break;
03006 case '\t':
03007 if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
03008 {
03009 EDIT_EM_ReplaceSel(hwnd, es, TRUE, "\t");
03010 if (es->flags & EF_UPDATE) {
03011 es->flags &= ~EF_UPDATE;
03012 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
03013 }
03014 }
03015 break;
03016 case VK_BACK:
03017 if (!(es->style & ES_READONLY) && !control) {
03018 if (es->selection_start != es->selection_end)
03019 EDIT_WM_Clear(hwnd, es);
03020 else {
03021
03022 EDIT_EM_SetSel(hwnd, es, -1, 0, FALSE);
03023 EDIT_MoveBackward(hwnd, es, TRUE);
03024 EDIT_WM_Clear(hwnd, es);
03025 }
03026 }
03027 break;
03028
03029 case 0x03:
03030 SendMessageA(hwnd, WM_COPY, 0, 0);
03031 break;
03032 case 0x16:
03033 SendMessageA(hwnd, WM_PASTE, 0, 0);
03034 break;
03035 case 0x18:
03036 SendMessageA(hwnd, WM_CUT, 0, 0);
03037 break;
03038
03039 default:
03040 if (!(es->style & ES_READONLY) && ((BYTE)c >= ' ') && (c != 127))
03041 {
03042 char str[2];
03043
03044 if (es->style & ES_NUMBER)
03045 {
03046 if (((BYTE)c < '0') || ((BYTE)c > '9')) {
03047 MessageBeep(MB_ICONEXCLAMATION);
03048 return;
03049 }
03050 }
03051 str[0] = c;
03052 str[1] = '\0';
03053 EDIT_EM_ReplaceSel(hwnd, es, TRUE, str);
03054 if (es->flags & EF_UPDATE)
03055 {
03056 es->flags &= ~EF_UPDATE;
03057 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
03058 }
03059 } else MessageBeep(MB_ICONEXCLAMATION);
03060 break;
03061 }
03062 }
03063
03064
03065
03066
03067
03068
03069
03070 static void EDIT_WM_Command(HWND hwnd, EDITSTATE *es, INT code, INT id, HWND control)
03071 {
03072 if (code || control)
03073 return;
03074
03075 switch (id) {
03076 case EM_UNDO:
03077 EDIT_EM_Undo(hwnd, es);
03078 break;
03079 case WM_CUT:
03080 EDIT_WM_Cut(hwnd, es);
03081 break;
03082 case WM_COPY:
03083 EDIT_WM_Copy(hwnd, es);
03084 break;
03085 case WM_PASTE:
03086 EDIT_WM_Paste(hwnd, es);
03087 break;
03088 case WM_CLEAR:
03089 EDIT_WM_Clear(hwnd, es);
03090 break;
03091 case EM_SETSEL:
03092 EDIT_EM_SetSel(hwnd, es, 0, -1, FALSE);
03093 EDIT_EM_ScrollCaret(hwnd, es);
03094 break;
03095 default:
03096
03097 break;
03098 }
03099 }
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118 static void EDIT_WM_ContextMenu(HWND hwnd, EDITSTATE *es, HWND hwndBtn, INT x, INT y)
03119 {
03120 HMENU menu = LoadMenuA(GetModuleHandleA("USER32"), "EDITMENU");
03121 HMENU popup = GetSubMenu(menu, 0);
03122 UINT start = es->selection_start;
03123 UINT end = es->selection_end;
03124
03125 ORDER_UINT(start, end);
03126
03127
03128 EnableMenuItem(popup, 0, MF_BYPOSITION | (EDIT_EM_CanUndo(hwnd, es) ? MF_ENABLED : MF_GRAYED));
03129
03130 EnableMenuItem(popup, 2, MF_BYPOSITION | ((end - start) && !(es->style & (ES_PASSWORD | ES_READONLY)) ? MF_ENABLED : MF_GRAYED));
03131
03132 EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
03133
03134 EnableMenuItem(popup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_TEXT) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
03135
03136 EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
03137
03138 EnableMenuItem(popup, 7, MF_BYPOSITION | (start || (end != lstrlenA(es->text)) ? MF_ENABLED : MF_GRAYED));
03139
03140 TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, 0, hwnd, NULL);
03141 DestroyMenu(menu);
03142 }
03143
03144
03145
03146
03147
03148
03149
03150 static void EDIT_WM_Copy(HWND hwnd, EDITSTATE *es)
03151 {
03152 INT s = es->selection_start;
03153 INT e = es->selection_end;
03154 HGLOBAL hdst;
03155 LPSTR dst;
03156
03157 if (e == s)
03158 return;
03159 ORDER_INT(s, e);
03160 hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1));
03161 dst = (LPSTR)GlobalLock(hdst);
03162 lstrcpynA(dst, es->text + s, e - s + 1);
03163 GlobalUnlock(hdst);
03164 OpenClipboard(hwnd);
03165 EmptyClipboard();
03166 SetClipboardData(CF_TEXT, hdst);
03167 CloseClipboard();
03168 }
03169
03170
03171
03172
03173
03174
03175
03176 static LRESULT EDIT_WM_Create(HWND hwnd, EDITSTATE *es, LPCREATESTRUCTA cs)
03177 {
03178
03179
03180
03181
03182
03183
03184 EDIT_WM_SetFont(hwnd, es, 0, FALSE);
03185 EDIT_EM_EmptyUndoBuffer(hwnd, es);
03186 if (cs->lpszName && *(cs->lpszName) != '\0') {
03187 EDIT_EM_ReplaceSel(hwnd, es, FALSE, cs->lpszName);
03188
03189
03190
03191
03192
03193 es->selection_start = es->selection_end = 0;
03194 EDIT_EM_ScrollCaret(hwnd, es);
03195 if (es->flags & EF_UPDATE) {
03196 es->flags &= ~EF_UPDATE;
03197 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
03198 }
03199 }
03200 return 0;
03201 }
03202
03203
03204
03205
03206
03207
03208
03209 static void EDIT_WM_Destroy(HWND hwnd, EDITSTATE *es)
03210 {
03211 if (!es)
03212 return;
03213
03214 if (es->hloc) {
03215 while (LocalUnlock(es->hloc)) ;
03216 LocalFree(es->hloc);
03217 }
03218
03219 HeapDestroy(es->heap);
03220 HeapFree(GetProcessHeap(), 0, es);
03221 SetInfoPtr(hwnd,0);
03222 }
03223
03224
03225
03226
03227
03228
03229
03230 static LRESULT EDIT_WM_EraseBkGnd(HWND hwnd, EDITSTATE *es, HDC dc)
03231 {
03232 HBRUSH brush;
03233 RECT rc;
03234
03235 HideCaret(hwnd);
03236
03237 if (!es->bEnableState || (es->style & ES_READONLY))
03238 brush = (HBRUSH)EDIT_SEND_CTLCOLORSTATIC(hwnd, dc);
03239 else
03240 brush = (HBRUSH)EDIT_SEND_CTLCOLOR(hwnd, dc);
03241
03242 if (!brush)
03243 brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
03244
03245 GetClientRect(hwnd, &rc);
03246 IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
03247 GetClipBox(dc, &rc);
03248
03249
03250
03251
03252
03253
03254 FillRect(dc, &rc, brush);
03255
03256 ShowCaret(hwnd);
03257
03258 return -1;
03259 }
03260
03261
03262
03263
03264
03265
03266
03267 static INT EDIT_WM_GetText(HWND hwnd, EDITSTATE *es, INT count, LPSTR text)
03268 {
03269 INT len;
03270
03271 if (es->text == NULL)
03272 return 0;
03273
03274 len = min(count, lstrlenA(es->text)+1);
03275 lstrcpynA(text, es->text, len);
03276 return len;
03277 }
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289 static LRESULT EDIT_HScroll_Hack(HWND hwnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
03290 {
03291 INT dx = 0;
03292 INT fw = es->format_rect.right - es->format_rect.left;
03293 LRESULT ret = 0;
03294
03295 if (!(es->flags & EF_HSCROLL_HACK)) {
03296
03297
03298
03299 es->flags |= EF_HSCROLL_HACK;
03300 }
03301
03302 switch (action) {
03303 case SB_LINELEFT:
03304 if (es->x_offset)
03305 dx = -es->char_width;
03306 break;
03307 case SB_LINERIGHT:
03308 if (es->x_offset < es->text_width)
03309 dx = es->char_width;
03310 break;
03311 case SB_PAGELEFT:
03312 if (es->x_offset)
03313 dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
03314 break;
03315 case SB_PAGERIGHT:
03316 if (es->x_offset < es->text_width)
03317 dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
03318 break;
03319 case SB_LEFT:
03320 if (es->x_offset)
03321 dx = -es->x_offset;
03322 break;
03323 case SB_RIGHT:
03324 if (es->x_offset < es->text_width)
03325 dx = es->text_width - es->x_offset;
03326 break;
03327 case SB_THUMBTRACK:
03328 es->flags |= EF_HSCROLL_TRACK;
03329 dx = pos * es->text_width / 100 - es->x_offset;
03330 break;
03331 case SB_THUMBPOSITION:
03332 es->flags &= ~EF_HSCROLL_TRACK;
03333 if (!(dx = pos * es->text_width / 100 - es->x_offset))
03334 EDIT_NOTIFY_PARENT(hwnd, EN_HSCROLL);
03335 break;
03336 case SB_ENDSCROLL:
03337 break;
03338
03339 default:
03340
03341 return 0;
03342 }
03343 if (dx)
03344 EDIT_EM_LineScroll(hwnd, es, dx, 0);
03345 return ret;
03346 }
03347
03348
03349
03350
03351
03352
03353
03354 static LRESULT EDIT_WM_HScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
03355 {
03356 INT dx;
03357 INT fw;
03358
03359 if (!(es->style & ES_MULTILINE))
03360 return 0;
03361
03362 if (!(es->style & ES_AUTOHSCROLL))
03363 return 0;
03364
03365 if (!(es->style & WS_HSCROLL))
03366 return EDIT_HScroll_Hack(hwnd, es, action, pos, scroll_bar);
03367
03368 dx = 0;
03369 fw = es->format_rect.right - es->format_rect.left;
03370 switch (action) {
03371 case SB_LINELEFT:
03372 if (es->x_offset)
03373 dx = -es->char_width;
03374 break;
03375 case SB_LINERIGHT:
03376 if (es->x_offset < es->text_width)
03377 dx = es->char_width;
03378 break;
03379 case SB_PAGELEFT:
03380 if (es->x_offset)
03381 dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
03382 break;
03383 case SB_PAGERIGHT:
03384 if (es->x_offset < es->text_width)
03385 dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
03386 break;
03387 case SB_LEFT:
03388 if (es->x_offset)
03389 dx = -es->x_offset;
03390 break;
03391 case SB_RIGHT:
03392 if (es->x_offset < es->text_width)
03393 dx = es->text_width - es->x_offset;
03394 break;
03395 case SB_THUMBTRACK:
03396 es->flags |= EF_HSCROLL_TRACK;
03397 dx = pos - es->x_offset;
03398 break;
03399 case SB_THUMBPOSITION:
03400 es->flags &= ~EF_HSCROLL_TRACK;
03401 if (!(dx = pos - es->x_offset)) {
03402 SetScrollPos(hwnd, SB_HORZ, pos, TRUE);
03403 EDIT_NOTIFY_PARENT(hwnd, EN_HSCROLL);
03404 }
03405 break;
03406 case SB_ENDSCROLL:
03407 break;
03408
03409 default:
03410
03411 return 0;
03412 }
03413 if (dx)
03414 EDIT_EM_LineScroll(hwnd, es, dx, 0);
03415 return 0;
03416 }
03417
03418
03419
03420
03421
03422
03423
03424 static BOOL EDIT_CheckCombo(HWND hwnd, EDITSTATE *es, UINT msg, INT key, DWORD key_data)
03425 {
03426 HWND hLBox = es->hwndListBox;
03427 HWND hCombo;
03428 BOOL bDropped;
03429 int nEUI;
03430
03431 if (!hLBox)
03432 return FALSE;
03433
03434 hCombo = GetParent(hwnd);
03435 bDropped = TRUE;
03436 nEUI = 0;
03437
03438
03439
03440
03441 if (key == VK_UP || key == VK_DOWN)
03442 {
03443 if (SendMessageA(hCombo, CB_GETEXTENDEDUI, 0, 0))
03444 nEUI = 1;
03445
03446 if (msg == WM_KEYDOWN || nEUI)
03447 bDropped = (BOOL)SendMessageA(hCombo, CB_GETDROPPEDSTATE, 0, 0);
03448 }
03449
03450 switch (msg)
03451 {
03452 case WM_KEYDOWN:
03453 if (!bDropped && nEUI && (key == VK_UP || key == VK_DOWN))
03454 {
03455
03456 SendMessageA(hCombo, CB_SETEXTENDEDUI, FALSE, 0);
03457 key = VK_F4;
03458 nEUI = 2;
03459 }
03460
03461 SendMessageA(hLBox, WM_KEYDOWN, (WPARAM)key, 0);
03462 break;
03463
03464 case WM_SYSKEYDOWN:
03465 if (nEUI)
03466 SendMessageA(hCombo, CB_SHOWDROPDOWN, bDropped ? FALSE : TRUE, 0);
03467 else
03468 SendMessageA(hLBox, WM_KEYDOWN, (WPARAM)VK_F4, 0);
03469 break;
03470 }
03471
03472 if(nEUI == 2)
03473 SendMessageA(hCombo, CB_SETEXTENDEDUI, TRUE, 0);
03474
03475 return TRUE;
03476 }
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486 static LRESULT EDIT_WM_KeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data)
03487 {
03488 BOOL shift;
03489 BOOL control;
03490
03491 if (GetKeyState(VK_MENU) & 0x8000)
03492 return 0;
03493
03494 shift = GetKeyState(VK_SHIFT) & 0x8000;
03495 control = GetKeyState(VK_CONTROL) & 0x8000;
03496
03497 switch (key) {
03498 case VK_F4:
03499 case VK_UP:
03500 if (EDIT_CheckCombo(hwnd,es, WM_KEYDOWN, key, key_data) || key == VK_F4)
03501 break;
03502
03503 case VK_LEFT:
03504 if ((es->style & ES_MULTILINE) && (key == VK_UP))
03505 EDIT_MoveUp_ML(hwnd, es, shift);
03506 else
03507 if (control)
03508 EDIT_MoveWordBackward(hwnd, es, shift);
03509 else
03510 EDIT_MoveBackward(hwnd, es, shift);
03511 break;
03512 case VK_DOWN:
03513 if (EDIT_CheckCombo(hwnd,es, WM_KEYDOWN, key, key_data))
03514 break;
03515
03516 case VK_RIGHT:
03517 if ((es->style & ES_MULTILINE) && (key == VK_DOWN))
03518 EDIT_MoveDown_ML(hwnd, es, shift);
03519 else if (control)
03520 EDIT_MoveWordForward(hwnd, es, shift);
03521 else
03522 EDIT_MoveForward(hwnd, es, shift);
03523 break;
03524 case VK_HOME:
03525 EDIT_MoveHome(hwnd, es, shift);
03526 break;
03527 case VK_END:
03528 EDIT_MoveEnd(hwnd, es, shift);
03529 break;
03530 case VK_PRIOR:
03531 if (es->style & ES_MULTILINE)
03532 EDIT_MovePageUp_ML(hwnd, es, shift);
03533 else
03534 EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key, key_data);
03535 break;
03536 case VK_NEXT:
03537 if (es->style & ES_MULTILINE)
03538 EDIT_MovePageDown_ML(hwnd, es, shift);
03539 else
03540 EDIT_CheckCombo(hwnd, es, WM_KEYDOWN, key, key_data);
03541 break;
03542 case VK_DELETE:
03543 if (!(es->style & ES_READONLY) && !(shift && control)) {
03544 if (es->selection_start != es->selection_end) {
03545 if (shift)
03546 EDIT_WM_Cut(hwnd, es);
03547 else
03548 EDIT_WM_Clear(hwnd, es);
03549 } else {
03550 if (shift) {
03551
03552 EDIT_EM_SetSel(hwnd, es, -1, 0, FALSE);
03553 EDIT_MoveBackward(hwnd, es, TRUE);
03554 EDIT_WM_Clear(hwnd, es);
03555 } else if (control) {
03556
03557 EDIT_EM_SetSel(hwnd, es, -1, 0, FALSE);
03558 EDIT_MoveEnd(hwnd, es, TRUE);
03559 EDIT_WM_Clear(hwnd, es);
03560 } else {
03561
03562 EDIT_EM_SetSel(hwnd, es, -1, 0, FALSE);
03563 EDIT_MoveForward(hwnd, es, TRUE);
03564 EDIT_WM_Clear(hwnd, es);
03565 }
03566 }
03567 }
03568 break;
03569 case VK_INSERT:
03570 if (shift) {
03571 if (!(es->style & ES_READONLY))
03572 EDIT_WM_Paste(hwnd, es);
03573 } else if (control)
03574 EDIT_WM_Copy(hwnd, es);
03575 break;
03576 case VK_RETURN:
03577
03578 if(!(es->style & ES_WANTRETURN))
03579 {
03580 HWND hwndParent = GetParent(hwnd);
03581 DWORD dw = SendMessageA( hwndParent, DM_GETDEFID, 0, 0 );
03582 if (HIWORD(dw) == DC_HASDEFID)
03583 {
03584 SendMessageA( hwndParent, WM_COMMAND,
03585 MAKEWPARAM( LOWORD(dw), BN_CLICKED ),
03586 (LPARAM)GetDlgItem( hwndParent, LOWORD(dw) ) );
03587 }
03588 }
03589 break;
03590 }
03591 return 0;
03592 }
03593
03594
03595
03596
03597
03598
03599
03600 static LRESULT EDIT_WM_KillFocus(HWND hwnd, EDITSTATE *es, HWND window_getting_focus)
03601 {
03602 es->flags &= ~EF_FOCUSED;
03603 DestroyCaret();
03604 if(!(es->style & ES_NOHIDESEL))
03605 EDIT_InvalidateText(hwnd, es, es->selection_start, es->selection_end);
03606 EDIT_NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
03607 return 0;
03608 }
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618 static LRESULT EDIT_WM_LButtonDblClk(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y)
03619 {
03620 INT s;
03621 INT e = es->selection_end;
03622 INT l;
03623 INT li;
03624 INT ll;
03625
03626 if (!(es->flags & EF_FOCUSED))
03627 return 0;
03628
03629 l = EDIT_EM_LineFromChar(hwnd, es, e);
03630 li = EDIT_EM_LineIndex(hwnd, es, l);
03631 ll = EDIT_EM_LineLength(hwnd, es, e);
03632 s = li + EDIT_CallWordBreakProc (hwnd, es, li, e - li, ll, WB_LEFT);
03633 e = li + EDIT_CallWordBreakProc(hwnd, es, li, e - li, ll, WB_RIGHT);
03634 EDIT_EM_SetSel(hwnd, es, s, e, FALSE);
03635 EDIT_EM_ScrollCaret(hwnd, es);
03636 return 0;
03637 }
03638
03639
03640
03641
03642
03643
03644
03645 static LRESULT EDIT_WM_LButtonDown(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y)
03646 {
03647 INT e;
03648 BOOL after_wrap;
03649
03650 if (!(es->flags & EF_FOCUSED))
03651 SetFocus(hwnd);
03652
03653 es->bCaptureState = TRUE;
03654 SetCapture(hwnd);
03655 EDIT_ConfinePoint(hwnd, es, &x, &y);
03656 e = EDIT_CharFromPos(hwnd, es, x, y, &after_wrap);
03657 EDIT_EM_SetSel(hwnd, es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
03658 EDIT_EM_ScrollCaret(hwnd, es);
03659 es->region_posx = es->region_posy = 0;
03660 SetTimer(hwnd, 0, 100, NULL);
03661 return 0;
03662 }
03663
03664
03665
03666
03667
03668
03669
03670 static LRESULT EDIT_WM_LButtonUp(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y)
03671 {
03672 if (es->bCaptureState)
03673 {
03674 KillTimer(hwnd,0);
03675 ReleaseCapture();
03676 }
03677 es->bCaptureState = FALSE;
03678
03679 return 0;
03680 }
03681
03682 static LRESULT EDIT_WM_CaptureChanged(HWND hwnd,EDITSTATE *es)
03683 {
03684 if (es->bCaptureState) KillTimer(hwnd,0);
03685 es->bCaptureState = FALSE;
03686
03687 return 0;
03688 }
03689
03690
03691
03692
03693
03694
03695 static LRESULT EDIT_WM_MouseMove(HWND hwnd, EDITSTATE *es, DWORD keys, INT x, INT y)
03696 {
03697 INT e;
03698 BOOL after_wrap;
03699 INT prex, prey;
03700
03701 if (!es->bCaptureState) return 0;
03702
03703
03704
03705
03706
03707 prex = x; prey = y;
03708 EDIT_ConfinePoint(hwnd, es, &x, &y);
03709 es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
03710 es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
03711 e = EDIT_CharFromPos(hwnd, es, x, y, &after_wrap);
03712 EDIT_EM_SetSel(hwnd, es, es->selection_start, e, after_wrap);
03713
03714 return 0;
03715 }
03716
03717
03718
03719
03720
03721
03722
03723 static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTA cs)
03724 {
03725 EDITSTATE *es;
03726
03727 if (!(es = (EDITSTATE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*es))))
03728 return FALSE;
03729 SetInfoPtr(hwnd,(DWORD)es);
03730
03731
03732
03733
03734
03735
03736
03737 if (!(es->heap = HeapCreate(0, 0x10000, 0)))
03738 return FALSE;
03739 es->style = cs->style;
03740
03741 es->bEnableState = !(cs->style & WS_DISABLED);
03742
03743
03744
03745
03746
03747
03748 if (es->style & WS_BORDER)
03749 {
03750 es->style &= ~WS_BORDER;
03751 SetWindowLongA(hwnd,GWL_STYLE,GetWindowLongA(hwnd,GWL_STYLE) & ~WS_BORDER);
03752 SetWindowLongA(hwnd,GWL_EXSTYLE,GetWindowLongA(hwnd,GWL_EXSTYLE) | WS_EX_CLIENTEDGE);
03753 }
03754
03755 if (es->style & ES_COMBO)
03756 es->hwndListBox = GetDlgItem(cs->hwndParent, ID_CB_LISTBOX);
03757
03758 if (es->style & ES_MULTILINE) {
03759 es->buffer_size = BUFSTART_MULTI;
03760 es->buffer_limit = BUFLIMIT_MULTI;
03761 if (es->style & WS_VSCROLL)
03762 es->style |= ES_AUTOVSCROLL;
03763 if (es->style & WS_HSCROLL)
03764 es->style |= ES_AUTOHSCROLL;
03765 es->style &= ~ES_PASSWORD;
03766 if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
03767 if (es->style & ES_RIGHT)
03768 es->style &= ~ES_CENTER;
03769 es->style &= ~WS_HSCROLL;
03770 es->style &= ~ES_AUTOHSCROLL;
03771 }
03772
03773
03774 es->style |= ES_AUTOVSCROLL;
03775 } else {
03776 es->buffer_size = BUFSTART_SINGLE;
03777 es->buffer_limit = BUFLIMIT_SINGLE;
03778 es->style &= ~ES_CENTER;
03779 es->style &= ~ES_RIGHT;
03780 es->style &= ~WS_HSCROLL;
03781 es->style &= ~WS_VSCROLL;
03782 es->style &= ~ES_AUTOVSCROLL;
03783 es->style &= ~ES_WANTRETURN;
03784 if (es->style & ES_UPPERCASE) {
03785 es->style &= ~ES_LOWERCASE;
03786 es->style &= ~ES_NUMBER;
03787 } else if (es->style & ES_LOWERCASE)
03788 es->style &= ~ES_NUMBER;
03789 if (es->style & ES_PASSWORD)
03790 es->password_char = '*';
03791
03792
03793 es->style |= ES_AUTOHSCROLL;
03794 }
03795 if (!(es->text = (char*)HeapAlloc(es->heap, 0, es->buffer_size + 1)))
03796 return FALSE;
03797 es->buffer_size = HeapSize(es->heap, 0, es->text) - 1;
03798 if (!(es->undo_text = (char*)HeapAlloc(es->heap, 0, es->buffer_size + 1)))
03799 return FALSE;
03800 es->undo_buffer_size = HeapSize(es->heap, 0, es->undo_text) - 1;
03801 *es->text = '\0';
03802 if (es->style & ES_MULTILINE)
03803 if (!(es->first_line_def = (LINEDEF*)HeapAlloc(es->heap, HEAP_ZERO_MEMORY, sizeof(LINEDEF))))
03804 return FALSE;
03805 es->line_count = 1;
03806
03807 return TRUE;
03808 }
03809
03810 static VOID EDIT_Draw(HWND hwnd,EDITSTATE *es,HDC hdc,BOOL eraseBkGnd)
03811 {
03812 INT i;
03813 HFONT old_font = 0;
03814 RECT rc;
03815 RECT rcLine;
03816 RECT rcRgn;
03817 BOOL rev = es->bEnableState && ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL));
03818
03819 HideCaret(hwnd);
03820
03821 if (eraseBkGnd)
03822 {
03823 HBRUSH brush;
03824
03825 if (!es->bEnableState || (es->style & ES_READONLY))
03826 brush = (HBRUSH)EDIT_SEND_CTLCOLORSTATIC(hwnd, hdc);
03827 else
03828 brush = (HBRUSH)EDIT_SEND_CTLCOLOR(hwnd, hdc);
03829
03830 if (!brush)
03831 brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
03832
03833 GetClientRect(hwnd, &rc);
03834
03835
03836
03837
03838
03839
03840 FillRect(hdc, &rc, brush);
03841 }
03842
03843 if(es->style & WS_BORDER)
03844 {
03845 GetClientRect(hwnd, &rc);
03846 if(es->style & ES_MULTILINE)
03847 {
03848 if(es->style & WS_HSCROLL) rc.bottom++;
03849 if(es->style & WS_VSCROLL) rc.right++;
03850 }
03851 Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
03852 }
03853
03854 IntersectClipRect(hdc, es->format_rect.left,
03855 es->format_rect.top,
03856 es->format_rect.right,
03857 es->format_rect.bottom);
03858 if (es->style & ES_MULTILINE)
03859 {
03860 GetClientRect(hwnd, &rc);
03861 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
03862 }
03863 if (es->font) old_font = SelectObject(hdc, es->font);
03864 if (!es->bEnableState || (es->style & ES_READONLY))
03865 EDIT_SEND_CTLCOLORSTATIC(hwnd, hdc);
03866 else
03867 EDIT_SEND_CTLCOLOR(hwnd, hdc);
03868 if (!es->bEnableState)
03869 SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
03870 GetClipBox(hdc, &rcRgn);
03871 if (es->style & ES_MULTILINE)
03872 {
03873 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
03874
03875 for (i = es->y_offset ; i <= MIN(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++)
03876 {
03877 EDIT_GetLineRect(hwnd,hdc, es, i, 0, -1, &rcLine);
03878 if (IntersectRect(&rc, &rcRgn, &rcLine))
03879 EDIT_PaintLine(hwnd, es, hdc, i, rev);
03880 }
03881 } else
03882 {
03883 EDIT_GetLineRect(hwnd,hdc, es, 0, 0, -1, &rcLine);
03884 if (IntersectRect(&rc, &rcRgn, &rcLine))
03885 EDIT_PaintLine(hwnd, es, hdc, 0, rev);
03886 }
03887 if (es->font) SelectObject(hdc, old_font);
03888 if (es->flags & EF_FOCUSED)
03889 EDIT_SetCaretPos(hwnd, es, es->selection_end,es->flags & EF_AFTER_WRAP);
03890
03891 ShowCaret(hwnd);
03892 }
03893
03894 static VOID EDIT_Refresh(HWND hwnd,EDITSTATE *es,BOOL useCache)
03895 {
03896 HDC hdc,hdcCompatible;
03897 HBITMAP bitmap,oldbmp;
03898 RECT rect;
03899
03900 if (es->flags & EF_UPDATE)
03901 {
03902
03903
03904 EDIT_NOTIFY_PARENT(hwnd,EN_UPDATE);
03905 }
03906
03907 if (!IsWindowVisible(hwnd)) return;
03908
03909 if (!useCache)
03910 {
03911 InvalidateRect(hwnd,NULL,TRUE);
03912 return;
03913 }
03914
03915
03916 HideCaret(hwnd);
03917 GetClientRect(hwnd,&rect);
03918 hdc = GetDC(hwnd);
03919 hdcCompatible = CreateCompatibleDC(hdc);
03920 bitmap = CreateCompatibleBitmap(hdc,rect.right,rect.bottom);
03921 oldbmp = SelectObject(hdcCompatible,bitmap);
03922 EDIT_Draw(hwnd,es,hdcCompatible,TRUE);
03923 SelectClipRgn(hdcCompatible,0);
03924 BitBlt(hdc,0,0,rect.right,rect.bottom,hdcCompatible,0,0,SRCCOPY);
03925 SelectObject(hdcCompatible,oldbmp);
03926 DeleteObject(bitmap);
03927 DeleteDC(hdcCompatible);
03928 ReleaseDC(hwnd,hdc);
03929 ShowCaret(hwnd);
03930 }
03931
03932
03933
03934
03935
03936
03937 static void EDIT_WM_Paint(HWND hwnd, EDITSTATE *es,WPARAM wParam)
03938 {
03939 PAINTSTRUCT ps;
03940 HDC hdc;
03941
03942 if (!wParam) hdc = BeginPaint(hwnd, &ps);
03943 else hdc = (HDC) wParam;
03944
03945 EDIT_Draw(hwnd,es,hdc,FALSE);
03946
03947 if (!wParam) EndPaint(hwnd, &ps);
03948 }
03949
03950
03951
03952
03953
03954
03955
03956 static void EDIT_WM_Paste(HWND hwnd, EDITSTATE *es)
03957 {
03958 HGLOBAL hsrc;
03959 LPSTR src;
03960
03961 OpenClipboard(hwnd);
03962 hsrc = GetClipboardData(CF_TEXT);
03963 if (hsrc) {
03964 src = (LPSTR)GlobalLock(hsrc);
03965 EDIT_EM_ReplaceSel(hwnd, es, TRUE, src);
03966 GlobalUnlock(hsrc);
03967
03968 if (es->flags & EF_UPDATE) {
03969 es->flags &= ~EF_UPDATE;
03970 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
03971 }
03972 }
03973 CloseClipboard();
03974 }
03975
03976
03977
03978
03979
03980
03981
03982 static void EDIT_WM_SetFocus(HWND hwnd, EDITSTATE *es, HWND window_losing_focus)
03983 {
03984 es->flags |= EF_FOCUSED;
03985 CreateCaret(hwnd, 0, 2, es->line_height);
03986 EDIT_SetCaretPos(hwnd, es, es->selection_end,
03987 es->flags & EF_AFTER_WRAP);
03988 if(!(es->style & ES_NOHIDESEL))
03989 EDIT_InvalidateText(hwnd, es, es->selection_start, es->selection_end);
03990 ShowCaret(hwnd);
03991 EDIT_NOTIFY_PARENT(hwnd, EN_SETFOCUS);
03992 }
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003 static void EDIT_WM_SetFont(HWND hwnd, EDITSTATE *es, HFONT font, BOOL redraw)
04004 {
04005 TEXTMETRICA tm;
04006 HDC dc;
04007 HFONT old_font = 0;
04008 RECT r;
04009
04010 dc = GetDC(hwnd);
04011 if (font)
04012 old_font = SelectObject(dc, font);
04013 if (!GetTextMetricsA(dc, &tm))
04014 {
04015 if (font) SelectObject(dc,old_font);
04016 ReleaseDC(hwnd,dc);
04017
04018 return;
04019 }
04020 es->font = font;
04021 es->line_height = tm.tmHeight;
04022
04023 es->char_width = tm.tmAveCharWidth;
04024 if (font)
04025 SelectObject(dc, old_font);
04026 ReleaseDC(hwnd, dc);
04027 if (font)
04028 EDIT_EM_SetMargins(hwnd, es, EC_LEFTMARGIN | EC_RIGHTMARGIN,
04029 EC_USEFONTINFO, EC_USEFONTINFO);
04030
04031 GetClientRect(hwnd, &r);
04032 EDIT_SetRectNP(hwnd, es, &r);
04033 if (es->style & ES_MULTILINE)
04034 EDIT_BuildLineDefs_ML(hwnd,es);
04035
04036 if (redraw)
04037 EDIT_Refresh(hwnd,es,FALSE);
04038 if (es->flags & EF_FOCUSED) {
04039 DestroyCaret();
04040 CreateCaret(hwnd, 0, 2, es->line_height);
04041 EDIT_SetCaretPos(hwnd, es, es->selection_end,
04042 es->flags & EF_AFTER_WRAP);
04043 ShowCaret(hwnd);
04044 }
04045 }
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060 static void EDIT_WM_SetText(HWND hwnd, EDITSTATE *es, LPCSTR text)
04061 {
04062 #ifdef __WIN32OS2__
04063
04064
04065
04066 if(text && es->text) {
04067 if(!strcmp(es->text, text)) {
04068 return;
04069 }
04070 }
04071 #endif
04072 es->selection_start = 0;
04073 es->selection_end = lstrlenA(es->text);
04074 if (es->flags & EF_FOCUSED)
04075 EDIT_SetCaretPos(hwnd, es, es->selection_end, FALSE);
04076
04077 if (text) {
04078
04079 EDIT_EM_ReplaceSel(hwnd, es, FALSE, text);
04080 } else {
04081
04082 EDIT_EM_ReplaceSel(hwnd, es, FALSE, "");
04083 }
04084 es->x_offset = 0;
04085 if (es->style & ES_MULTILINE) {
04086 es->flags &= ~EF_UPDATE;
04087 } else {
04088 es->flags |= EF_UPDATE;
04089 }
04090 es->flags &= ~EF_MODIFIED;
04091 EDIT_EM_SetSel(hwnd, es, 0, 0, FALSE);
04092 EDIT_EM_ScrollCaret(hwnd, es);
04093 EDIT_UpdateScrollBars(hwnd,es,TRUE,TRUE);
04094 if (es->flags & EF_UPDATE)
04095 {
04096 EDIT_NOTIFY_PARENT(hwnd,EN_UPDATE);
04097
04098
04099
04100
04101 EDIT_NOTIFY_PARENT(hwnd, EN_CHANGE);
04102 es->flags &= ~EF_UPDATE;
04103 }
04104 }
04105
04106
04107
04108
04109
04110
04111
04112 static void EDIT_WM_Size(HWND hwnd, EDITSTATE *es, UINT action, INT width, INT height)
04113 {
04114 if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
04115 RECT rc;
04116 SetRect(&rc, 0, 0, width, height);
04117 EDIT_SetRectNP(hwnd, es, &rc);
04118 EDIT_Refresh(hwnd,es,FALSE);
04119 }
04120 }
04121
04122
04123
04124
04125
04126
04127
04128 static LRESULT EDIT_WM_SysKeyDown(HWND hwnd, EDITSTATE *es, INT key, DWORD key_data)
04129 {
04130 if ((key == VK_BACK) && (key_data & 0x2000)) {
04131 if (EDIT_EM_CanUndo(hwnd, es))
04132 EDIT_EM_Undo(hwnd, es);
04133 return 0;
04134 } else if ((key == VK_UP) || (key == VK_DOWN))
04135 {
04136 if (EDIT_CheckCombo(hwnd,es, WM_SYSKEYDOWN, key, key_data))
04137 return 0;
04138 }
04139 return DefWindowProcA(hwnd, WM_SYSKEYDOWN, (WPARAM)key, (LPARAM)key_data);
04140 }
04141
04142
04143
04144
04145
04146
04147
04148 static void EDIT_WM_Timer(HWND hwnd, EDITSTATE *es, INT id, TIMERPROC timer_proc)
04149 {
04150 if (es->region_posx < 0) {
04151 EDIT_MoveBackward(hwnd, es, TRUE);
04152 } else if (es->region_posx > 0) {
04153 EDIT_MoveForward(hwnd, es, TRUE);
04154 }
04155
04156 if (!(es->style & ES_MULTILINE)) return;
04157
04158 if (es->region_posy < 0)
04159 {
04160 EDIT_MoveUp_ML(hwnd,es,TRUE);
04161 } else if (es->region_posy > 0)
04162 {
04163 EDIT_MoveDown_ML(hwnd,es,TRUE);
04164 }
04165 }
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177 static LRESULT EDIT_VScroll_Hack(HWND hwnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
04178 {
04179 INT dy = 0;
04180 LRESULT ret = 0;
04181
04182 if (!(es->flags & EF_VSCROLL_HACK)) {
04183
04184
04185
04186 es->flags |= EF_VSCROLL_HACK;
04187 }
04188
04189 switch (action) {
04190 case SB_LINEUP:
04191 case SB_LINEDOWN:
04192 case SB_PAGEUP:
04193 case SB_PAGEDOWN:
04194 EDIT_EM_Scroll(hwnd, es, action);
04195 return 0;
04196 case SB_TOP:
04197 dy = -es->y_offset;
04198 break;
04199 case SB_BOTTOM:
04200 dy = es->line_count - 1 - es->y_offset;
04201 break;
04202 case SB_THUMBTRACK:
04203 es->flags |= EF_VSCROLL_TRACK;
04204 dy = (pos * (es->line_count - 1) + 50) / 100 - es->y_offset;
04205 break;
04206 case SB_THUMBPOSITION:
04207 es->flags &= ~EF_VSCROLL_TRACK;
04208 if (!(dy = (pos * (es->line_count - 1) + 50) / 100 - es->y_offset))
04209 EDIT_NOTIFY_PARENT(hwnd, EN_VSCROLL);
04210 break;
04211 case SB_ENDSCROLL:
04212 break;
04213
04214 default:
04215
04216 return 0;
04217 }
04218 if (dy)
04219 EDIT_EM_LineScroll(hwnd, es, 0, dy);
04220 return ret;
04221 }
04222
04223
04224
04225
04226
04227
04228
04229 static LRESULT EDIT_WM_VScroll(HWND hwnd, EDITSTATE *es, INT action, INT pos, HWND scroll_bar)
04230 {
04231 INT dy;
04232
04233 if (!(es->style & ES_MULTILINE))
04234 return 0;
04235
04236 if (!(es->style & ES_AUTOVSCROLL))
04237 return 0;
04238
04239 if (!(es->style & WS_VSCROLL))
04240 return EDIT_VScroll_Hack(hwnd, es, action, pos, scroll_bar);
04241
04242 dy = 0;
04243 switch (action) {
04244 case SB_LINEUP:
04245 case SB_LINEDOWN:
04246 case SB_PAGEUP:
04247 case SB_PAGEDOWN:
04248 EDIT_EM_Scroll(hwnd, es, action);
04249 return 0;
04250
04251 case SB_TOP:
04252 dy = -es->y_offset;
04253 break;
04254 case SB_BOTTOM:
04255 dy = es->line_count - 1 - es->y_offset;
04256 break;
04257 case SB_THUMBTRACK:
04258 es->flags |= EF_VSCROLL_TRACK;
04259 dy = pos - es->y_offset;
04260 break;
04261 case SB_THUMBPOSITION:
04262 es->flags &= ~EF_VSCROLL_TRACK;
04263 if (!(dy = pos - es->y_offset)) {
04264 SetScrollPos(hwnd, SB_VERT, pos, TRUE);
04265 EDIT_NOTIFY_PARENT(hwnd, EN_VSCROLL);
04266 }
04267 break;
04268 case SB_ENDSCROLL:
04269 break;
04270
04271 default:
04272
04273
04274 return 0;
04275 }
04276 if (dy)
04277 EDIT_EM_LineScroll(hwnd, es, 0, dy);
04278 return 0;
04279 }
04280
04281 static LRESULT EDIT_WM_MouseWheel(HWND hwnd,EDITSTATE *es,WPARAM wParam,LPARAM lParam)
04282 {
04283 short gcWheelDelta = 0;
04284 UINT pulScrollLines = 3;
04285 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
04286
04287 if (wParam & (MK_SHIFT | MK_CONTROL))
04288 return DefWindowProcA(hwnd,WM_MOUSEWHEEL, wParam, lParam);
04289 gcWheelDelta -= (short) HIWORD(wParam);
04290 if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
04291 {
04292 int cLineScroll= (int) min((UINT) es->line_count, pulScrollLines);
04293
04294 cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
04295 return EDIT_EM_LineScroll(hwnd, es, 0, cLineScroll);
04296 }
04297
04298 return 0;
04299 }
04300
04301 BOOL EDIT_Register()
04302 {
04303 WNDCLASSA wndClass;
04304
04305
04306
04307
04308 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
04309 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
04310 wndClass.lpfnWndProc = (WNDPROC)EditWndProc;
04311 wndClass.cbClsExtra = 0;
04312 wndClass.cbWndExtra = sizeof(VOID*);
04313 wndClass.hCursor = LoadCursorA(0,IDC_IBEAMA);
04314 wndClass.hbrBackground = (HBRUSH)0;
04315 wndClass.lpszClassName = EDITCLASSNAME;
04316
04317 return RegisterClassA(&wndClass);
04318 }
04319
04320 BOOL EDIT_Unregister()
04321 {
04322 if (GlobalFindAtomA(EDITCLASSNAME))
04323 return UnregisterClassA(EDITCLASSNAME,(HINSTANCE)NULL);
04324 else return FALSE;
04325 }