c0ef56d001d8bfa06a34fef86b02ee9121e40971
[reactos.git] / rosapps / devutils / vmingw / editor.cpp
1 /********************************************************************
2 * Module: editor.cpp. This is part of Visual-MinGW.
3 *
4 * Purpose: Procedures to manage Scintilla editor.
5 *
6 * Authors: These classes are based on SciTE release 1.39.
7 * http://www.scintilla.org/
8 * SciTE original code by Neil Hodgson.
9 * Present revised code by Manu B.
10 *
11 * License: Both SciTE and Scintilla are covered by
12 * "License for Scintilla and SciTE" agreement terms detailed in license.htm.
13 * Present revised code is covered by GNU General Public License.
14 *
15 * Revisions:
16 *
17 ********************************************************************/
18 #include <windows.h>
19 #include <stdio.h>
20 #include "commctrl.h"
21 #include "commdlg.h"
22 #include "editor.h"
23 #include "rsrc.h"
24
25 extern CMessageBox MsgBox;
26
27 int Minimum(int a, int b);
28 int Maximum(int a, int b);
29
30 int Minimum(int a, int b){
31 if (a < b)
32 return a;
33 else
34 return b;
35 }
36
37 int Maximum(int a, int b){
38 if (a > b)
39 return a;
40 else
41 return b;
42 }
43
44 void EnsureRangeVisible(HWND hwndCtrl, int posStart, int posEnd, bool enforcePolicy){
45 int lineStart = SendMessage(hwndCtrl, SCI_LINEFROMPOSITION, Minimum(posStart, posEnd), 0);
46 int lineEnd = SendMessage(hwndCtrl, SCI_LINEFROMPOSITION, Maximum(posStart, posEnd), 0);
47 for (int line = lineStart; line <= lineEnd; line++){
48 SendMessage(hwndCtrl,
49 enforcePolicy ? SCI_ENSUREVISIBLEENFORCEPOLICY : SCI_ENSUREVISIBLE, line, 0);
50 }
51 }
52
53 int LengthDocument(HWND hwndCtrl){
54 return SendMessage(hwndCtrl, SCI_GETLENGTH, 0, 0);
55 }
56
57 CharacterRange GetSelection(HWND hwndCtrl){
58 CharacterRange crange;
59 crange.cpMin = SendMessage(hwndCtrl, SCI_GETSELECTIONSTART, 0, 0);
60 crange.cpMax = SendMessage(hwndCtrl, SCI_GETSELECTIONEND, 0, 0);
61 return crange;
62 }
63
64
65 /********************************************************************
66 * Class: CChooseFontDlg.
67 *
68 * Purpose:
69 *
70 * Revisions:
71 *
72 ********************************************************************/
73 CChooseFontDlg::CChooseFontDlg(){
74 ZeroMemory(&lf, sizeof(LOGFONT));
75 /* lf.lfHeight;
76 lf.lfWidth;
77 lf.lfEscapement;
78 lf.lfOrientation;
79 lf.lfWeight;
80 lf.lfItalic;
81 lf.lfUnderline;
82 lf.lfStrikeOut;
83 lf.lfCharSet;
84 lf.lfOutPrecision;
85 lf.lfClipPrecision;
86 lf.lfQuality;
87 lf.lfPitchAndFamily;
88 lf.lfFaceName[LF_FACESIZE];*/
89
90 cf.lStructSize = sizeof(CHOOSEFONT);
91 cf.hwndOwner = 0;
92 cf.hDC = NULL;
93 cf.lpLogFont = &lf;//&(Profile.LogFont);
94 cf.iPointSize = 0;
95 cf.Flags = /*CF_INITTOLOGFONTSTRUCT
96 |*/ CF_SCREENFONTS | CF_EFFECTS
97 /*| CF_ENABLEHOOK*/;
98 cf.rgbColors = 0;//Profile.rgbForeColor;
99 cf.lCustData = 0;
100 cf.lpfnHook = NULL;
101 cf.lpTemplateName = NULL;
102 cf.hInstance = NULL;
103 cf.lpszStyle = NULL;
104 cf.nFontType = SCREEN_FONTTYPE;
105 cf.nSizeMin = 0;
106 cf.nSizeMax = 0;
107 }
108
109 CChooseFontDlg::~CChooseFontDlg(){
110 }
111
112 bool CChooseFontDlg::Create(CWindow * pWindow){
113 cf.hwndOwner = pWindow->_hWnd;
114 return ChooseFont(&cf);
115 }
116
117
118 /*bool ChooseNewFont(HWND hWndListBox){
119 static CHOOSEFONT cf;
120 static BOOL bFirstTime = TRUE;
121 HFONT hFont;
122 if(bFirstTime){
123 bFirstTime = false;
124 }
125 if(ChooseFont(&cf)){
126 HDC hDC;
127 hFont = CreateFontIndirect( &(Profile.LogFont) );
128 hDC = GetDC( hWndListBox );
129 SelectObject( hDC, hFont );
130 Profile.rgbForeColor = cf.rgbColors;
131 InvalidateRect( hWndListBox, NULL, TRUE );
132 SendMessage( hWndListBox, WM_CTLCOLORLISTBOX, (DWORD) hDC, (LONG) hWndListBox );
133 SendMessage( hWndListBox, WM_SETFONT, (DWORD) hFont, TRUE );
134 ReleaseDC( hWndListBox, hDC );
135 }
136 return true;
137 }*/
138
139
140 /********************************************************************
141 * Class: CFindReplaceDlg.
142 *
143 * Purpose:
144 *
145 * Revisions:
146 *
147 ********************************************************************/
148 CFindReplaceDlg::CFindReplaceDlg(){
149 pEditor = NULL;
150 hEditor = 0;
151 resId = 0;
152 *findWhat = '\0';
153 *replaceWhat = '\0';
154
155 bWholeWord = false;
156 bMatchCase = true;
157 bRegExp = false;
158 bWrapFind = false;
159 bUnSlash = false;
160 bReverseFind = false;
161 bHavefound = false;
162 }
163
164 CFindReplaceDlg::~CFindReplaceDlg(){
165 }
166
167 HWND CFindReplaceDlg::Find(CScintilla * pEditor){
168 if (_hWnd || !pEditor)
169 return 0;
170 return CreateParam(pEditor, IDD_FIND, (long) IDD_FIND);
171 }
172
173 HWND CFindReplaceDlg::Replace(CScintilla * pEditor){
174 if (_hWnd || !pEditor)
175 return 0;
176 return CreateParam(pEditor, IDD_REPLACE, (long) IDD_REPLACE);
177 }
178
179 LRESULT CALLBACK CFindReplaceDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){
180 switch(Message){
181 case WM_INITDIALOG:
182 return OnInitDialog((HWND) wParam, lParam);
183
184 case WM_COMMAND:
185 OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam);
186 break;
187
188 case WM_CLOSE:
189 EndDlg(0);
190 break;
191 }
192 return FALSE;
193 }
194
195 BOOL CFindReplaceDlg::OnInitDialog(HWND, LPARAM lInitParam){
196 // Set pointers.
197 pEditor = (CEditor *) _pParent;
198 if (pEditor == NULL)
199 return TRUE;
200
201 hEditor = pEditor->_hWnd;
202 resId = lInitParam;
203
204 hFindWhat = GetItem(IDC_FINDWHAT);
205 hWholeWord = GetItem(IDC_WHOLEWORD);
206 hMatchCase = GetItem(IDC_MATCHCASE);
207 hRegExp = GetItem(IDC_REGEXP);
208 hWrap = GetItem(IDC_WRAP);
209 hUnSlash = GetItem(IDC_UNSLASH);
210
211 if (resId == IDD_FIND)
212 return Find_OnInitDialog();
213 else if (resId == IDD_REPLACE)
214 return Replace_OnInitDialog();
215 return FALSE;
216 }
217
218 BOOL CFindReplaceDlg::Find_OnInitDialog(void){
219
220 hUp = GetItem(IDC_DIRECTIONUP);
221 hDown = GetItem(IDC_DIRECTIONDOWN);
222
223 SetItemText(hFindWhat, findWhat);
224 //FillComboFromMemory(wFindWhat, memFinds);
225 if (bWholeWord)
226 ::SendMessage(hWholeWord, BM_SETCHECK, BST_CHECKED, 0);
227 if (bMatchCase)
228 ::SendMessage(hMatchCase, BM_SETCHECK, BST_CHECKED, 0);
229 if (bRegExp)
230 ::SendMessage(hRegExp, BM_SETCHECK, BST_CHECKED, 0);
231 if (bWrapFind)
232 ::SendMessage(hWrap, BM_SETCHECK, BST_CHECKED, 0);
233 if (bUnSlash)
234 ::SendMessage(hUnSlash, BM_SETCHECK, BST_CHECKED, 0);
235
236 if (bReverseFind) {
237 ::SendMessage(hUp, BM_SETCHECK, BST_CHECKED, 0);
238 } else {
239 ::SendMessage(hDown, BM_SETCHECK, BST_CHECKED, 0);
240 }
241 return TRUE;
242 }
243
244 BOOL CFindReplaceDlg::Replace_OnInitDialog(void){
245 SetItemText(hFindWhat, findWhat);
246 //FillComboFromMemory(wFindWhat, sci->memFinds);
247
248 hReplaceWith = GetItem(IDC_REPLACEWITH);
249 SetItemText(hReplaceWith, replaceWhat);
250 //FillComboFromMemory(wReplaceWith, sci->memReplaces);
251
252 if (bWholeWord)
253 ::SendMessage(hWholeWord, BM_SETCHECK, BST_CHECKED, 0);
254 if (bMatchCase)
255 ::SendMessage(hMatchCase, BM_SETCHECK, BST_CHECKED, 0);
256 if (bRegExp)
257 ::SendMessage(hRegExp, BM_SETCHECK, BST_CHECKED, 0);
258 if (bWrapFind)
259 ::SendMessage(hWrap, BM_SETCHECK, BST_CHECKED, 0);
260 if (bUnSlash)
261 ::SendMessage(hUnSlash, BM_SETCHECK, BST_CHECKED, 0);
262 if ((findWhat) != '\0'){
263 ::SetFocus(hReplaceWith);
264 return FALSE;
265 }
266 return TRUE;
267 }
268
269 BOOL CFindReplaceDlg::OnCommand(WORD, WORD wID, HWND){
270 if (resId == IDD_FIND)
271 return Find_OnCommand(wID);
272 else if (resId == IDD_REPLACE)
273 return Replace_OnCommand(wID);
274 return FALSE;
275 }
276
277 BOOL CFindReplaceDlg::Find_OnCommand(WORD wID){
278 switch (wID){
279 case IDOK:
280 char s[200];
281 GetItemText(hFindWhat, s, sizeof(s));
282 strcpy(findWhat, s);
283 //memFinds.Insert(s);
284 bWholeWord = BST_CHECKED ==
285 ::SendMessage(hWholeWord, BM_GETCHECK, 0, 0);
286 bMatchCase = BST_CHECKED ==
287 ::SendMessage(hMatchCase, BM_GETCHECK, 0, 0);
288 bRegExp = BST_CHECKED ==
289 ::SendMessage(hRegExp, BM_GETCHECK, 0, 0);
290 bWrapFind = BST_CHECKED ==
291 ::SendMessage(hWrap, BM_GETCHECK, 0, 0);
292 bUnSlash = BST_CHECKED ==
293 ::SendMessage(hUnSlash, BM_GETCHECK, 0, 0);
294 bReverseFind = BST_CHECKED ==
295 ::SendMessage(hUp, BM_GETCHECK, 0, 0);
296
297 FindNext(bReverseFind, true);
298 return TRUE;
299
300 case IDCANCEL:
301 EndDlg(IDCANCEL);
302 return FALSE;
303 }
304 return FALSE;
305 }
306
307 BOOL CFindReplaceDlg::Replace_OnCommand(WORD wID){
308 if (wID == IDCANCEL){
309 EndDlg(IDCANCEL);
310 return FALSE;
311 }else{
312 return HandleReplaceCommand(wID);
313 }
314 return FALSE;
315 }
316
317 void CFindReplaceDlg::FindNext(bool reverseDirection, bool showWarnings){
318 if (!hEditor){
319 MsgBox.DisplayWarning("Can't get editor handle");
320 return;
321 }
322
323 if (!findWhat[0]) { // nothing to found
324 //Find(hEditor);
325 return;
326 }
327 char findTarget[FR_MAX_LEN + 1];
328 strcpy(findTarget, findWhat);
329
330 // for C conversions -> int lenFind = UnSlashAsNeeded(findTarget, unSlash, regExp);
331 int lenFind = strlen(findTarget); // normal return of UnSlashAsNeeded
332
333 if (lenFind == 0)
334 return;
335
336 CharacterRange cr = GetSelection(hEditor);
337 int startPosition = cr.cpMax;
338 int endPosition = LengthDocument(hEditor);
339
340 if (reverseDirection){
341 startPosition = cr.cpMin - 1;
342 endPosition = 0;
343 }
344
345 int flags = (bWholeWord ? SCFIND_WHOLEWORD : 0) |
346 (bMatchCase ? SCFIND_MATCHCASE : 0) |
347 (bRegExp ? SCFIND_REGEXP : 0);
348
349 ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0);
350 ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0);
351 ::SendMessage(hEditor, SCI_SETSEARCHFLAGS, flags, 0);
352 int posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, lenFind, (LPARAM) findTarget);
353
354 if (posFind == -1 && bWrapFind){ // not found with wrapFind
355
356 // Failed to find in indicated direction
357 // so search from the beginning (forward) or from the end (reverse)
358 // unless wrapFind is false
359 if (reverseDirection){
360 startPosition = LengthDocument(hEditor);
361 endPosition = 0;
362 } else {
363 startPosition = 0;
364 endPosition = LengthDocument(hEditor);
365 }
366 ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0);
367 ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0);
368 posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, lenFind, (LPARAM) findTarget);
369 }
370 if (posFind == -1){ // not found
371 bHavefound = false;
372 if (showWarnings){
373
374 /*warn that not found
375 WarnUser(warnNotFound);*/
376
377 if (strlen(findWhat) > FR_MAX_LEN)
378 findWhat[FR_MAX_LEN] = '\0';
379 char msg[FR_MAX_LEN + 50];
380 strcpy(msg, "Cannot find the string \"");
381 strcat(msg, findWhat);
382 strcat(msg, "\".");
383 if (_hWnd){
384 MsgBox.DisplayWarning(msg);
385 }else{
386 MessageBox(0, msg, "Message", MB_OK);
387 }
388 }
389 }else{ // found
390 bHavefound = true;
391 int start = ::SendMessage(hEditor, SCI_GETTARGETSTART, 0, 0);
392 int end = ::SendMessage(hEditor, SCI_GETTARGETEND, 0, 0);
393 EnsureRangeVisible(hEditor, start, end, true);
394 ::SendMessage(hEditor, SCI_SETSEL, start, end);
395 }
396 }
397
398 BOOL CFindReplaceDlg::HandleReplaceCommand(int cmd){
399 if (!hEditor){
400 MsgBox.DisplayWarning("Can't get editor handle");
401 return false;
402 }
403
404 if ((cmd == IDOK) || (cmd == IDC_REPLACE) || (cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)) {
405 GetItemText(hFindWhat, findWhat, sizeof(findWhat));
406 //props.Set("find.what", findWhat);
407 //memFinds.Insert(findWhat);
408
409 bWholeWord = BST_CHECKED ==
410 ::SendMessage(hWholeWord, BM_GETCHECK, 0, 0);
411 bMatchCase = BST_CHECKED ==
412 ::SendMessage(hMatchCase, BM_GETCHECK, 0, 0);
413 bRegExp = BST_CHECKED ==
414 ::SendMessage(hRegExp, BM_GETCHECK, 0, 0);
415 bWrapFind = BST_CHECKED ==
416 ::SendMessage(hWrap, BM_GETCHECK, 0, 0);
417 bUnSlash = BST_CHECKED ==
418 ::SendMessage(hUnSlash, BM_GETCHECK, 0, 0);
419 }
420 if ((cmd == IDC_REPLACE) || (cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)) {
421 GetItemText(hReplaceWith, replaceWhat, sizeof(replaceWhat));
422 //memReplaces.Insert(replaceWhat);
423 }
424
425 if (cmd == IDOK) {
426 FindNext(bReverseFind, true); // Find next
427 } else if (cmd == IDC_REPLACE) {
428 if (bHavefound){
429 ReplaceOnce();
430 } else {
431 CharacterRange crange = GetSelection(hEditor);
432 ::SendMessage(hEditor, SCI_SETSEL, crange.cpMin, crange.cpMin);
433 FindNext(bReverseFind, true);
434 if (bHavefound){
435 ReplaceOnce();
436 }
437 }
438 } else if ((cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)){
439 ReplaceAll(cmd == IDC_REPLACEINSEL);
440 }
441 return TRUE;
442 }
443
444 void CFindReplaceDlg::ReplaceOnce(void){
445 if (bHavefound){
446 char replaceTarget[FR_MAX_LEN + 1];
447 strcpy(replaceTarget, replaceWhat);
448 // for C conversions -> int replaceLen = UnSlashAsNeeded(replaceTarget, unSlash, regExp);
449 int replaceLen = strlen(replaceTarget); // normal return of UnSlashAsNeeded
450
451 CharacterRange cr = GetSelection(hEditor);
452 ::SendMessage(hEditor, SCI_SETTARGETSTART, cr.cpMin, 0);
453 ::SendMessage(hEditor, SCI_SETTARGETEND, cr.cpMax, 0);
454 int lenReplaced = replaceLen;
455 if (bRegExp)
456 lenReplaced = ::SendMessage(hEditor, SCI_REPLACETARGETRE, replaceLen, (LPARAM) replaceTarget);
457 else // Allow \0 in replacement
458 ::SendMessage(hEditor, SCI_REPLACETARGET, replaceLen, (LPARAM) replaceTarget);
459 ::SendMessage(hEditor, SCI_SETSEL, cr.cpMin + lenReplaced, cr.cpMin);
460 bHavefound = false;
461 }
462 FindNext(bReverseFind, true);
463 }
464
465 void CFindReplaceDlg::ReplaceAll(bool inSelection){
466 char findTarget[FR_MAX_LEN + 1];
467 strcpy(findTarget, findWhat);
468
469 // for C conversions -> int findLen = UnSlashAsNeeded(findTarget, unSlash, regExp);
470 int findLen = strlen(findTarget); // normal return of UnSlashAsNeeded
471
472 if (findLen == 0) {
473 MessageBox(_hWnd, "Find string for \"Replace All\" must not be empty.", "Message", MB_OK | MB_ICONWARNING);
474 return;
475 }
476
477 CharacterRange cr = GetSelection(hEditor);
478 int startPosition = cr.cpMin;
479 int endPosition = cr.cpMax;
480 if (inSelection) {
481 if (startPosition == endPosition) {
482 MessageBox(_hWnd, "Selection for \"Replace in Selection\" must not be empty.", "Message", MB_OK | MB_ICONWARNING);
483 return;
484 }
485 } else {
486 endPosition = LengthDocument(hEditor);
487 if (bWrapFind) {
488 // Whole document
489 startPosition = 0;
490 }
491 // If not wrapFind, replace all only from caret to end of document
492 }
493
494 char replaceTarget[FR_MAX_LEN + 1];
495 strcpy(replaceTarget, replaceWhat);
496
497 // for C conversions -> int replaceLen = UnSlashAsNeeded(replaceTarget, unSlash, regExp);
498 int replaceLen = strlen(replaceTarget); // normal return of UnSlashAsNeeded
499
500 int flags = (bWholeWord ? SCFIND_WHOLEWORD : 0) |
501 (bMatchCase ? SCFIND_MATCHCASE : 0) |
502 (bRegExp ? SCFIND_REGEXP : 0);
503 ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0);
504 ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0);
505 ::SendMessage(hEditor, SCI_SETSEARCHFLAGS, flags, 0);
506 int posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, findLen, (LPARAM) findTarget);
507 if ((findLen == 1) && bRegExp && (findTarget[0] == '^')) {
508 // Special case for replace all start of line so it hits the first line
509 posFind = startPosition;
510 ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0);
511 ::SendMessage(hEditor, SCI_SETTARGETEND, startPosition, 0);
512 }
513 if ((posFind != -1) && (posFind <= endPosition)) {
514 int lastMatch = posFind;
515 ::SendMessage(hEditor, SCI_BEGINUNDOACTION, 0, 0);
516 while (posFind != -1) {
517 int lenTarget = ::SendMessage(hEditor, SCI_GETTARGETEND, 0, 0) - ::SendMessage(hEditor, SCI_GETTARGETSTART, 0, 0);
518 int lenReplaced = replaceLen;
519 if (bRegExp)
520 lenReplaced = ::SendMessage(hEditor, SCI_REPLACETARGETRE, replaceLen, (LPARAM) replaceTarget);
521 else
522 ::SendMessage(hEditor, SCI_REPLACETARGET, replaceLen, (LPARAM) replaceTarget);
523 // Modify for change caused by replacement
524 endPosition += lenReplaced - lenTarget;
525 lastMatch = posFind + lenReplaced;
526 // For the special cases of start of line and end of line
527 // Something better could be done but there are too many special cases
528 if (lenTarget <= 0)
529 lastMatch++;
530 ::SendMessage(hEditor, SCI_SETTARGETSTART, lastMatch, 0);
531 ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0);
532 posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, findLen, (LPARAM) findTarget);
533 }
534 if (inSelection)
535 ::SendMessage(hEditor, SCI_SETSEL, startPosition, endPosition);
536 else
537 ::SendMessage(hEditor, SCI_SETSEL, lastMatch, lastMatch);
538 ::SendMessage(hEditor, SCI_ENDUNDOACTION, 0, 0);
539 } else {
540 if (strlen(findWhat) > FR_MAX_LEN)
541 findWhat[FR_MAX_LEN] = '\0';
542 char msg[FR_MAX_LEN + 50];
543 strcpy(msg, "No replacements because string \"");
544 strcat(msg, findWhat);
545 strcat(msg, "\" was not present.");
546 MessageBox(_hWnd, msg, "Message", MB_OK | MB_ICONWARNING);
547 }
548 }
549
550
551 /********************************************************************
552 * Class: CEditor.
553 *
554 * Purpose:
555 *
556 * Revisions:
557 *
558 ********************************************************************/
559 CEditor::CEditor(){
560 caretPos = 1;
561 }
562
563 CEditor::~CEditor(){
564 }
565
566 void CEditor::LoadFile(CFileItem * file){
567 if (!file || !_hWnd)
568 return;
569
570 if (file->nFileOffset == 0)
571 return; // Untitled file.
572
573 SetLexer(file->type);
574 ::SendMessage(_hWnd, SCI_CANCEL, 0, 0);
575 ::SendMessage(_hWnd, SCI_SETUNDOCOLLECTION, 0, 0);
576
577 FILE *fp = fopen(file->szFileName, "rb");
578 if (fp){
579 char data[blockSize];
580 int lenFile = fread(data, 1, sizeof(data), fp);
581
582 while (lenFile > 0){
583 ::SendMessage(_hWnd, SCI_ADDTEXT, lenFile, (LPARAM) data);
584 lenFile = fread(data, 1, sizeof(data), fp);
585 }
586
587 fclose(fp);
588
589 }else{
590 MsgBox.DisplayWarning("Can't load file %s", file->szFileName);
591 }
592
593 ::SendMessage(_hWnd, SCI_SETUNDOCOLLECTION, 1, 0);
594 ::SendMessage(_hWnd, EM_EMPTYUNDOBUFFER, 0, 0);
595 ::SendMessage(_hWnd, SCI_SETSAVEPOINT, 0 , 0);
596 ::SendMessage(_hWnd, SCI_GOTOPOS, 0, 0);
597 }
598
599 void GetFileType(CFileItem * file){
600 if (!file)
601 return;
602
603 if (file->nFileExtension){
604 char * ext = file->szFileName + file->nFileExtension;
605 // H_FILE ?
606 if (!stricmp(ext, "h")){
607 file->type = H_FILE;
608 return;
609 }else if (!stricmp(ext, "hpp")){
610 file->type = H_FILE;
611 return;
612 }else if (!stricmp(ext, "hxx")){
613 file->type = H_FILE;
614 return;
615 // C_FILE ?
616 }else if (!stricmp(ext, "c")){
617 file->type = C_FILE;
618 return;
619 }else if (!stricmp(ext, "cpp")){
620 file->type = C_FILE;
621 return;
622 }else if (!stricmp(ext, "cxx")){
623 file->type = C_FILE;
624 return;
625 // RC_FILE ?
626 }else if (!stricmp(ext, "rc")){
627 file->type = RC_FILE;
628 return;
629 }
630 }
631 file->type = U_FILE;
632 return;
633 }
634
635 void CEditor::SaveFile(char * fullPath){
636 if (!_hWnd)
637 return;
638
639 FILE *fp = fopen(fullPath, "wb");
640 if (fp){
641 char data[blockSize + 1];
642 int lengthDoc = ::SendMessage(_hWnd, SCI_GETLENGTH, 0, 0);
643 for (int i = 0; i < lengthDoc; i += blockSize) {
644 int grabSize = lengthDoc - i;
645 if (grabSize > blockSize)
646 grabSize = blockSize;
647 GetRange(i, i + grabSize, data);
648 fwrite(data, grabSize, 1, fp);
649 }
650 fclose(fp);
651 ::SendMessage(_hWnd, SCI_SETSAVEPOINT, 0, 0);
652
653 }else{
654 MsgBox.DisplayWarning("Can't save file %s", fullPath);
655 }
656 }
657
658 int CEditor::GetCurrentPos(void){
659 int currentPos = ::SendMessage(_hWnd, SCI_GETCURRENTPOS, 0,0);
660 caretPos = ::SendMessage(_hWnd, SCI_LINEFROMPOSITION, currentPos, 0) + 1;
661 return caretPos;
662 }
663
664 void CEditor::GetRange(int start, int end, char *text){
665 TextRange tr;
666 tr.chrg.cpMin = start;
667 tr.chrg.cpMax = end;
668 tr.lpstrText = text;
669 ::SendMessage(_hWnd, SCI_GETTEXTRANGE, 0, (LPARAM) &tr);
670 }
671
672 void CEditor::SetAStyle(int style, COLORREF fore, COLORREF back, int size, const char *face){
673 ::SendMessage(_hWnd, SCI_STYLESETFORE, style, fore);
674 ::SendMessage(_hWnd, SCI_STYLESETBACK, style, back);
675 if (size >= 1)
676 ::SendMessage(_hWnd, SCI_STYLESETSIZE, style, size);
677 if (face)
678 ::SendMessage(_hWnd, SCI_STYLESETFONT, style, (LPARAM) face);
679 }
680
681 void CEditor::DefineMarker(int marker, int markerType, COLORREF fore, COLORREF back) {
682 ::SendMessage(_hWnd, SCI_MARKERDEFINE, marker, markerType);
683 ::SendMessage(_hWnd, SCI_MARKERSETFORE, marker, fore);
684 ::SendMessage(_hWnd, SCI_MARKERSETBACK, marker, back);
685 }
686
687 void CEditor::SetLexer(int fileType){
688 switch (fileType){
689
690 case H_FILE:
691 case C_FILE:
692 case RC_FILE:
693 SetCppLexer();
694 return;
695
696 default:
697 // Global default style.
698 SetAStyle(STYLE_DEFAULT, black, white, 10, "Verdana");
699 ::SendMessage(_hWnd, SCI_STYLECLEARALL, 0, 0); // Copies to all other styles.
700
701 }
702 }
703
704 void CEditor::SetCppLexer(void){
705 ::SendMessage(_hWnd, SCI_SETLEXER, SCLEX_CPP, 0);
706 ::SendMessage(_hWnd, SCI_SETSTYLEBITS, 5, 0);
707
708 ::SendMessage(_hWnd, SCI_SETKEYWORDS, 0, (LPARAM) cppKeyWords);
709
710 // Global default style.
711 SetAStyle(STYLE_DEFAULT, black, white, 10, "Verdana");
712 ::SendMessage(_hWnd, SCI_STYLECLEARALL, 0, 0); // Copies to all other styles.
713
714 // C Styles.
715 SetAStyle(SCE_C_DEFAULT, black, white, 10, "Verdana"); //0
716 SetAStyle(SCE_C_COMMENT, Green, white, 0, 0); //1
717 SetAStyle(SCE_C_COMMENTLINE, Green, white, 0, 0); //2
718 SetAStyle(SCE_C_COMMENTDOC, darkGreen, white, 0, 0); //3
719 SetAStyle(SCE_C_NUMBER, Ice, white, 0, 0); //4
720 SetAStyle(SCE_C_WORD, darkBlue, white, 0, 0); //5
721 ::SendMessage(_hWnd, SCI_STYLESETBOLD, SCE_C_WORD, 1);
722 SetAStyle(SCE_C_STRING, Purple, white, 0, 0); //6
723 SetAStyle(SCE_C_CHARACTER, Purple, white, 0, 0); //7
724 SetAStyle(SCE_C_PREPROCESSOR, Olive, white, 0, 0); //9
725 SetAStyle(SCE_C_OPERATOR, black, white, 0, 0); //10
726 ::SendMessage(_hWnd, SCI_STYLESETBOLD, SCE_C_OPERATOR, 1);
727 // SetAStyle(SCE_C_STRINGEOL, darkBlue, white, 0, 0); //12
728 // SetAStyle(SCE_C_COMMENTLINEDOC, darkBlue, white, 0, 0); //15
729 // SetAStyle(SCE_C_WORD2, darkBlue, white, 0, 0); //16
730 ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold", (long)"1");
731 ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold.compact", (long)"1");
732 ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold.symbols", (long)"1");
733
734 ::SendMessage(_hWnd, SCI_SETFOLDFLAGS, 16, 0);
735
736 // To put the folder markers in the line number region
737 //SendEditor(SCI_SETMARGINMASKN, 0, SC_MASK_FOLDERS);
738
739 ::SendMessage(_hWnd, SCI_SETMODEVENTMASK, SC_MOD_CHANGEFOLD, 0);
740
741 // Create a margin column for the folding symbols
742 ::SendMessage(_hWnd, SCI_SETMARGINTYPEN, 2, SC_MARGIN_SYMBOL);
743
744 ::SendMessage(_hWnd, SCI_SETMARGINWIDTHN, 2, /*foldMargin ? foldMarginWidth :*/ 16);
745
746 ::SendMessage(_hWnd, SCI_SETMARGINMASKN, 2, SC_MASK_FOLDERS);
747 ::SendMessage(_hWnd, SCI_SETMARGINSENSITIVEN, 2, 1);
748
749 DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS, white, black);
750 DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS, white, black);
751 DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, white, black);
752 DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, white, black);
753 DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, white, black);
754 DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, white, black);
755 DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, white, black);
756
757 return;
758 }
759
760 void CEditor::GotoLine(int line, char * /*fileName*/){
761 ::SendMessage(_hWnd, SCI_ENSUREVISIBLEENFORCEPOLICY, line, 0);
762 ::SendMessage(_hWnd, SCI_GOTOLINE, line, 0);
763 }
764
765 bool CEditor::MarginClick(int position, int modifiers){
766 int lineClick = ::SendMessage(_hWnd, SCI_LINEFROMPOSITION, position, 0);
767 //Platform::DebugPrintf("Margin click %d %d %x\n", position, lineClick,
768 // ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, lineClick) & SC_FOLDLEVELHEADERFLAG);
769 /* if ((modifiers & SCMOD_SHIFT) && (modifiers & SCMOD_CTRL)) {
770 FoldAll();
771 } else {*/
772 int levelClick = ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, lineClick, 0);
773 if (levelClick & SC_FOLDLEVELHEADERFLAG) {
774 if (modifiers & SCMOD_SHIFT) {
775 // Ensure all children visible
776 ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 1);
777 Expand(lineClick, true, true, 100, levelClick);
778 } else if (modifiers & SCMOD_CTRL) {
779 if (::SendMessage(_hWnd, SCI_GETFOLDEXPANDED, lineClick, 0)) {
780 // Contract this line and all children
781 ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 0);
782 Expand(lineClick, false, true, 0, levelClick);
783 } else {
784 // Expand this line and all children
785 ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 1);
786 Expand(lineClick, true, true, 100, levelClick);
787 }
788 } else {
789 // Toggle this line
790 ::SendMessage(_hWnd, SCI_TOGGLEFOLD, lineClick, 0);
791 }
792 }
793 /* }*/
794 return true;
795 }
796
797 void CEditor::Expand(int &line, bool doExpand, bool force, int visLevels, int level){
798 int lineMaxSubord = ::SendMessage(_hWnd, SCI_GETLASTCHILD, line, level & SC_FOLDLEVELNUMBERMASK);
799 line++;
800 while (line <= lineMaxSubord) {
801 if (force) {
802 if (visLevels > 0)
803 ::SendMessage(_hWnd, SCI_SHOWLINES, line, line);
804 else
805 ::SendMessage(_hWnd, SCI_HIDELINES, line, line);
806 } else {
807 if (doExpand)
808 ::SendMessage(_hWnd, SCI_SHOWLINES, line, line);
809 }
810 int levelLine = level;
811 if (levelLine == -1)
812 levelLine = ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, line, 0);
813 if (levelLine & SC_FOLDLEVELHEADERFLAG) {
814 if (force) {
815 if (visLevels > 1)
816 ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 1);
817 else
818 ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 0);
819 Expand(line, doExpand, force, visLevels - 1);
820 } else {
821 if (doExpand) {
822 if (!::SendMessage(_hWnd, SCI_GETFOLDEXPANDED, line, 0))
823 ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 1);
824 Expand(line, true, force, visLevels - 1);
825 } else {
826 Expand(line, false, force, visLevels - 1);
827 }
828 }
829 } else {
830 line++;
831 }
832 }
833 }
834