1 /*
2 * Part of WCM Commander
3 * https://github.com/corporateshark/WCMCommander
4 * wcm@linderdaum.com
5 */
6
7 #if !defined( NOMINMAX )
8 #define NOMINMAX
9 #endif
10
11 #include "globals.h"
12 #include "nc.h"
13 #include "ncedit.h"
14 #include "ncwin.h"
15 #include "wcm-config.h"
16 #include "color-style.h"
17 #include "string-util.h"
18 #include "charsetdlg.h"
19 #include "ltext.h"
20 #include "globals.h"
21 #include "unicode_lc.h"
22
23 #include <algorithm>
24
25 int uiClassEditor = GetUiID( "Editor" );
26 static int uiShlDEF = GetUiID( "DEF" );
27 static int uiShlKEYWORD = GetUiID( "KEYWORD" );
28 static int uiShlCOMMENT = GetUiID( "COMMENT" );
29 static int uiShlSTRING = GetUiID( "STRING" );
30 static int uiShlPRE = GetUiID( "PRE" );
31 static int uiShlNUM = GetUiID( "NUM" );
32 static int uiShlOPER = GetUiID( "OPER" );
33 static int uiShlATTN = GetUiID( "ATTN" );
34 static int uiShl = GetUiID( "shl" );
35 static int uiColorCtrl = GetUiID( "ctrl-color" );
36 static int uiColorCursor = GetUiID( "cursor-color" );
37
38
OnChangeStyles()39 void EditWin::OnChangeStyles()
40 {
41 shlDEF = UiGetColor( uiShlDEF, uiShl, 0, 0x000000 );
42 shlKEYWORD = UiGetColor( uiShlKEYWORD, uiShl, 0, 0x00FFFF );
43 shlCOMMENT = UiGetColor( uiShlCOMMENT, uiShl, 0, 0x808080 );
44 shlSTRING = UiGetColor( uiShlSTRING, uiShl, 0, 0xFFFF00 );
45 shlPRE = UiGetColor( uiShlPRE, uiShl, 0, 0xFF00FF );
46 shlNUM = UiGetColor( uiShlNUM, uiShl, 0, 0xFFFFFF );
47 shlOPER = UiGetColor( uiShlOPER, uiShl, 0, 0xFF80FF );
48 shlATTN = UiGetColor( uiShlATTN, uiShl, 0, 0x0000FF );
49 color_text = UiGetColor( uiColor, 0, 0, 0 );
50 color_background = UiGetColor( uiBackground, 0, 0, 0xFFFFFF );
51 color_mark_text = UiGetColor( uiMarkColor, 0, 0, 0 );
52 color_mark_background = UiGetColor( uiMarkBackground, 0, 0, 0xFFFFFF );
53 color_ctrl = UiGetColor( uiColorCtrl, 0, 0, 0xFF0000 );
54 color_cursor = UiGetColor( uiColorCursor, 0, 0, 0x00FFFF );
55
56 wal::GC gc( this );
57 gc.Set( GetFont() );
58 cpoint p = gc.GetTextExtents( ABCString );
59 charW = p.x / ABCStringLen;
60 charH = p.y;
61
62 if ( !charW ) { charW = 10; }
63
64 if ( !charH ) { charH = 10; }
65
66 //как в EventSize !!!
67 rows = editRect.Height() / charH;
68 cols = editRect.Width() / charW;
69
70 if ( rows <= 0 ) { rows = 1; }
71
72 if ( cols <= 0 ) { cols = 1; }
73
74 CalcScroll();
75
76 {
77 int r = ( editRect.Height() + charH - 1 ) / charH;
78 int c = ( editRect.Width() + charW - 1 ) / charW;
79
80 if ( r < 1 ) { r = 1; }
81
82 if ( c < 1 ) { c = 1; }
83
84 screen.Alloc( r, c );
85 __RefreshScreenData();
86 Invalidate();
87 }
88
89 }
90
EditWin(Win * parent)91 EditWin::EditWin( Win* parent )
92 : Win( WT_CHILD, 0, parent ),
93 _lo( 2, 2 ),
94 charset( charset_table[GetFirstOperCharsetId()] ), //EditCSLatin1),
95 vscroll( 0, this, true, false ),
96 tabSize( g_WcmConfig.editTabSize ),
97 autoIdent( g_WcmConfig.editAutoIdent ),
98 firstLine( 0 ),
99 colOffset( 0 ),
100 rows( 0 ),
101 cols( 0 ),
102 charH( 1 ),
103 charW( 1 ),
104 recomendedCursorCol( -1 ),
105
106 _shl( 0 ),
107 _shlLine( -1 ),
108
109 _changed( false )
110 {
111 vscroll.Enable();
112 vscroll.Show();
113 vscroll.SetManagedWin( this );
114 _lo.AddWin( &vscroll, 0, 1 );
115 _lo.AddRect( &editRect, 0, 0 );
116 _lo.SetColGrowth( 0 );
117 SetLayout( &_lo );
118 LSRange lr( 0, 10000, 1000 );
119 LSize ls;
120 ls.x = ls.y = lr;
121 SetLSize( ls );
122
123 OnChangeStyles();
124
125 SetTimer( 0, 500 );
126 }
127
UiGetClassId()128 int EditWin::UiGetClassId() { return uiClassEditor; }
129
CursorToScreen()130 void EditWin::CursorToScreen()
131 {
132 int f = firstLine;
133
134 if ( cursor.line >= firstLine + rows )
135 {
136 firstLine = cursor.line - rows + 1;
137 }
138
139 if ( cursor.line < firstLine )
140 {
141 firstLine = cursor.line;
142 }
143
144 if ( f != firstLine )
145 {
146 CalcScroll();
147 }
148
149 int c = GetCursorCol();
150 int n = cols > 4 ? cols / 4 : 1;
151
152 if ( colOffset + cols <= c )
153 {
154 colOffset = c + n - cols;
155
156 if ( colOffset > c ) { colOffset = c; }
157 }
158
159 if ( c < colOffset ) { colOffset = c - n; }
160
161 if ( colOffset < 0 ) { colOffset = 0; }
162 }
163
CursorToScreen_forReplace()164 void EditWin::CursorToScreen_forReplace()
165 {
166 int f = firstLine;
167 firstLine = cursor.line - 2;
168
169 if ( firstLine < 0 ) { firstLine = 0; }
170
171 int c = GetCursorCol();
172 colOffset = ( c < cols ) ? 0 : c - cols;
173
174 if ( f != firstLine )
175 {
176 CalcScroll();
177 }
178 }
179
180
181
CursorLeft(bool mark)182 void EditWin::CursorLeft( bool mark )
183 {
184 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
185 ASSERT( cursor.pos >= 0 && cursor.pos <= text.Get( cursor.line ).Len() );
186
187 recomendedCursorCol = -1;
188 char* t = charset->GetPrev( text.Get( cursor.line ).Get() + cursor.pos, text.Get( cursor.line ).Get() );
189
190 bool refresh = false;
191
192 if ( t )
193 {
194 cursor.pos = t - text.Get( cursor.line ).Get();
195 refresh = true;
196 SendChanges();
197 }
198 else
199 {
200 if ( cursor.line > 0 )
201 {
202 cursor.line--;
203 cursor.pos = text.Get( cursor.line ).Len();
204 refresh = true;
205 SendChanges();
206 }
207 }
208
209 CursorToScreen();
210
211 if ( !mark ) { marker = cursor; }
212
213 if ( refresh ) { Refresh(); }
214 }
215
SetCursorPos(EditPoint p)216 void EditWin::SetCursorPos( EditPoint p )
217 {
218 if ( p.line >= text.Count() ) { p.line = text.Count() - 1; p.pos = 0; }
219
220 if ( p.line < 0 ) { p.line = 0; p.pos = 0; }
221
222 int l = text.Get( p.line ).Len();
223
224 if ( p.pos > l ) { p.pos = l; }
225
226 if ( p.pos < 0 ) { p.pos = 0; }
227
228 marker = cursor = p;
229
230 CursorToScreen();
231 SendChanges();
232 Refresh();
233 }
234
CursorHome(bool mark)235 void EditWin::CursorHome( bool mark )
236 {
237 recomendedCursorCol = -1;
238
239 if ( cursor.pos > 0 )
240 {
241 cursor.pos = 0;
242 }
243
244 CursorToScreen();
245 SendChanges();
246
247 if ( !mark ) { marker = cursor; }
248
249 Refresh();
250 }
251
CursorEnd(bool mark)252 void EditWin::CursorEnd( bool mark )
253 {
254 recomendedCursorCol = -1;
255 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
256
257 if ( cursor.pos < text.Get( cursor.line ).Len() )
258 {
259 cursor.pos = text.Get( cursor.line ).Len();
260 }
261
262 CursorToScreen();
263 SendChanges();
264
265 if ( !mark ) { marker = cursor; }
266
267 Refresh();
268 }
269
CursorRight(bool mark)270 void EditWin::CursorRight( bool mark )
271 {
272 recomendedCursorCol = -1;
273 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
274
275 if ( cursor.pos >= text.Get( cursor.line ).Len() )
276 {
277 if ( cursor.line + 1 < text.Count() )
278 {
279 cursor.line++;
280 cursor.pos = 0;
281 CursorToScreen();
282 SendChanges();
283
284 if ( !mark ) { marker = cursor; }
285
286 Refresh();
287 }
288
289 return;
290 }
291
292 //bool tab;
293 char* s = text.Get( cursor.line ).Get() + cursor.pos;
294 char* end = text.Get( cursor.line ).Get() + text.Get( cursor.line ).Len();
295 char* t = charset->GetNext( s, end );
296 cursor.pos = t ? ( t - text.Get( cursor.line ).Get() ) : text.Get( cursor.line ).Len();
297 CursorToScreen();
298 SendChanges();
299
300 if ( !mark ) { marker = cursor; }
301
302 Refresh();
303 }
304
305
CursorDown(bool mark)306 void EditWin::CursorDown( bool mark )
307 {
308 if ( cursor.line + 1 < text.Count() )
309 {
310 if ( recomendedCursorCol < 0 )
311 {
312 recomendedCursorCol = GetColFromPos( cursor.line, cursor.pos );
313 }
314
315 cursor.pos = GetPosFromCol( cursor.line + 1, recomendedCursorCol );
316 cursor.line++;
317 CursorToScreen();
318 SendChanges();
319
320 if ( !mark ) { marker = cursor; }
321
322 Refresh();
323 }
324 }
325
CursorUp(bool mark)326 void EditWin::CursorUp( bool mark )
327 {
328 if ( cursor.line > 0 )
329 {
330 if ( recomendedCursorCol < 0 )
331 {
332 recomendedCursorCol = GetColFromPos( cursor.line, cursor.pos );
333 }
334
335 cursor.pos = GetPosFromCol( cursor.line - 1, recomendedCursorCol );
336 cursor.line--;
337 CursorToScreen();
338 SendChanges();
339
340 if ( !mark ) { marker = cursor; }
341
342 Refresh();
343 }
344 }
345
StepLeft(EditPoint * p,unicode_t * c)346 bool EditWin::StepLeft( EditPoint* p, unicode_t* c )
347 {
348 if ( p->line < 0 || p->line >= text.Count() ) { return false; }
349
350 if ( p->pos < 0 || p->pos > text.Get( p->line ).Len() ) { return false; }
351
352 EditString& str = text.Get( p->line );
353 char* t = charset->GetPrev( str.Get() + p->pos, str.Get() );
354
355 if ( t )
356 {
357 p->pos = t - text.Get( p->line ).Get();
358 *c = charset->GetChar( t, str.Get() + str.Len() );
359 return true;
360 }
361
362 if ( p->line <= 0 ) { return false; }
363
364 p->line--;
365 p->pos = text.Get( p->line ).Len();
366 *c = ' ';
367 return true;
368 }
369
StepRight(EditPoint * p,unicode_t * c)370 bool EditWin::StepRight( EditPoint* p, unicode_t* c )
371 {
372 if ( p->line < 0 || p->line >= text.Count() ) { return false; }
373
374 if ( p->pos < 0 ) { return false; }
375
376
377 if ( p->pos >= text.Get( p->line ).Len() )
378 {
379 if ( p->line + 1 >= text.Count() ) { return false; }
380
381 p->line++;
382 p->pos = 0;
383 }
384 else
385 {
386 char* begin = text.Get( p->line ).Get();
387 int len = text.Get( p->line ).Len();
388 char* s = begin + p->pos;
389 char* end = begin + len;
390 char* t = charset->GetNext( s, end );
391 p->pos = t ? ( t - begin ) : len;
392 }
393
394 EditString& str = text.Get( p->line );
395 *c = str.Len() > p->pos ? charset->GetChar( str.Get() + p->pos, str.Get() + str.Len() ) : ' ';
396 return true;
397 }
398
CursorCtrlLeft(bool mark)399 void EditWin::CursorCtrlLeft( bool mark )
400 {
401 EditPoint p = cursor;
402 unicode_t c;
403
404 if ( !StepLeft( &p, &c ) ) { return; }
405
406 int group = EditBuf::GetCharGroup( c );
407 cursor = p;
408
409 while ( StepLeft( &p, &c ) && EditBuf::GetCharGroup( c ) == group )
410 {
411 if ( cursor.pos > 0 )
412 {
413 cursor = p;
414 }
415 else
416 {
417 cursor.pos = 0;
418 }
419 }
420
421 recomendedCursorCol = -1;
422 SendChanges();
423 CursorToScreen();
424
425 if ( !mark ) { marker = cursor; }
426
427 Refresh();
428 }
429
CursorCtrlRight(bool mark)430 void EditWin::CursorCtrlRight( bool mark )
431 {
432 EditPoint p = cursor;
433
434 if ( p.line < 0 || p.line >= text.Count() ) { return; }
435
436 if ( p.pos < 0 || p.pos > text.Get( p.line ).Len() ) { return; }
437
438 EditString& str = text.Get( p.line );
439 unicode_t c = str.Len() > 0 ? charset->GetChar( str.Get() + p.pos, str.Get() + str.Len() ) : ' ';
440
441 int group = EditBuf::GetCharGroup( c );
442
443 while ( StepRight( &p, &c ) )
444 {
445 if ( p.line > cursor.line )
446 {
447 cursor = p;
448 cursor.pos = 0;
449 break;
450 }
451 else
452 {
453 cursor = p;
454 }
455
456 if ( EditBuf::GetCharGroup( c ) != group ) { break; }
457 }
458
459 recomendedCursorCol = -1;
460 SendChanges();
461 CursorToScreen();
462
463 if ( !mark ) { marker = cursor; }
464
465 Refresh();
466 }
467
468
PageDown(bool mark)469 void EditWin::PageDown( bool mark )
470 {
471 CursorToScreen();
472
473 if ( recomendedCursorCol < 0 )
474 {
475 recomendedCursorCol = GetColFromPos( cursor.line, cursor.pos );
476 }
477
478 int lines = text.Count();
479
480 if ( firstLine + rows >= lines )
481 {
482 if ( lines > 0 && cursor.line + 1 < lines )
483 {
484 cursor.line = lines - 1;
485 cursor.pos = GetPosFromCol( cursor.line, recomendedCursorCol );
486 SendChanges();
487
488 if ( !mark ) { marker = cursor; }
489
490 Refresh();
491 return;
492 }
493 }
494
495 int addLines = rows - 1;
496
497 if ( firstLine + addLines + rows > lines )
498 {
499 addLines = lines - rows - firstLine;
500 }
501
502 if ( firstLine + addLines < 0 )
503 {
504 addLines = -firstLine;
505 }
506
507 //ASSERT(addLines >= 0);
508 firstLine += addLines;
509
510 if ( firstLine < 0 ) { firstLine = 0; }
511
512 if ( firstLine >= lines ) { firstLine = lines - 1; }
513
514 cursor.line += addLines;
515
516 if ( cursor.line < 0 ) { cursor.line = 0; }
517
518 if ( cursor.line >= lines ) { cursor.line = lines - 1; }
519
520 cursor.pos = GetPosFromCol( cursor.line, recomendedCursorCol );
521 CalcScroll();
522 SendChanges();
523
524 if ( !mark ) { marker = cursor; }
525
526 Refresh();
527 }
528
PageUp(bool mark)529 void EditWin::PageUp( bool mark )
530 {
531 CursorToScreen();
532
533 if ( recomendedCursorCol < 0 )
534 {
535 recomendedCursorCol = GetColFromPos( cursor.line, cursor.pos );
536 }
537
538 if ( firstLine == 0 )
539 {
540 if ( cursor.line > 0 )
541 {
542 cursor.line = 0;
543 cursor.pos = GetPosFromCol( cursor.line, recomendedCursorCol );
544 SendChanges();
545
546 if ( !mark ) { marker = cursor; }
547
548 Refresh();
549 return;
550 }
551 }
552
553 int minus = rows - 1;
554
555 if ( firstLine < minus )
556 {
557 minus = firstLine;
558 }
559
560 firstLine -= minus;
561 cursor.line -= minus;
562 cursor.pos = GetPosFromCol( cursor.line, recomendedCursorCol );
563 CalcScroll();
564 SendChanges();
565
566 if ( !mark ) { marker = cursor; }
567
568 Refresh();
569 }
570
CtrlPageDown(bool mark)571 void EditWin::CtrlPageDown( bool mark )
572 {
573 if ( !text.Count() ) { return; }
574
575 cursor.line = text.Count() - 1;
576 cursor.pos = text.Get( cursor.line ).Len();
577
578 CalcScroll();
579 SendChanges();
580 CursorToScreen();
581
582 if ( !mark ) { marker = cursor; }
583
584 Refresh();
585 }
586
CtrlPageUp(bool mark)587 void EditWin::CtrlPageUp( bool mark )
588 {
589 cursor.line = 0;
590 cursor.pos = 0;
591
592 CalcScroll();
593 SendChanges();
594 CursorToScreen();
595
596 if ( !mark ) { marker = cursor; }
597
598 Refresh();
599 }
600
601
SelectAll()602 void EditWin::SelectAll()
603 {
604 marker.Set( 0, 0 );
605 int n = text.Count() - 1;
606 cursor.Set( n, text.Get( n ).len );
607 CalcScroll();
608 CursorToScreen();
609 SendChanges();
610 Refresh();
611 }
612
GetCursorCol()613 int EditWin::GetCursorCol()
614 {
615 return GetColFromPos( cursor.line, cursor.pos );
616 }
617
GetCursorSymbol()618 int32_t EditWin::GetCursorSymbol()
619 {
620 if ( cursor.line >= text.Count() ) { return -1; }
621
622 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
623 EditString& str = text.Get( cursor.line );
624
625 if ( cursor.pos >= str.len ) { return -1; }
626
627 char* s = str.Get();
628 unicode_t c = charset->GetChar( s + cursor.pos, s + str.len );
629 return c;
630 }
631
Undo()632 bool EditWin::Undo()
633 {
634 UndoBlock* u = undoList.GetUndo();
635
636 if ( !u ) { return false; }
637
638 try
639 {
640 for ( UndoRec* r = u->last; r; r = r->prev )
641 {
642 if ( _shlLine > r->line ) { _shlLine = r->line; }
643
644 switch ( r->type )
645 {
646
647 case UndoRec::ATTR:
648 {
649 EditString& str = text.Get( r->line );
650 str.flags = r->prevAttr;
651 }
652 break;
653
654 case UndoRec::INSTEXT:
655 {
656 EditString& str = text.Get( r->line );
657 str.Delete( r->pos, r->dataSize );
658 }
659 break;
660
661 case UndoRec::DELTEXT:
662 {
663 EditString& str = text.Get( r->line );
664 str.Insert( r->data.data(), r->pos, r->dataSize );
665 }
666 break;
667
668 case UndoRec::DELLINE:
669 {
670 int n = r->line;
671 text.Insert( n, 1, r->attr );
672 text.Get( n ).Set( r->data.data(), r->dataSize );
673 }
674 break;
675
676 case UndoRec::ADDLINE:
677 {
678 int n = r->line;
679 text.Delete( n, 1 );
680 }
681 break;
682
683 default:
684 NCMessageBox( ( NCDialogParent* )Parent(), "bad oper", "undo", true );
685 undoList.Clear();
686 return false;
687 }
688 }
689
690 cursor = u->beginCursor;
691 marker = u->beginMarker;
692 _changed = u->editorChanged;
693 }
694 catch ( ... )
695 {
696 undoList.Clear();
697 throw;
698 }
699
700 CursorToScreen();
701 CalcScroll();
702 SendChanges();
703 Refresh();
704 return true;
705 }
706
Redo()707 bool EditWin::Redo()
708 {
709 bool chg;
710 UndoBlock* u = undoList.GetRedo( &chg );
711
712 if ( !u ) { return false; }
713
714 try
715 {
716 for ( UndoRec* r = u->first; r; r = r->next )
717 {
718 if ( _shlLine > r->line ) { _shlLine = r->line; }
719
720 switch ( r->type )
721 {
722
723 case UndoRec::ATTR:
724 {
725 EditString& str = text.Get( r->line );
726 str.flags = r->attr;
727 }
728 break;
729
730 case UndoRec::INSTEXT:
731 {
732 EditString& str = text.Get( r->line );
733 str.Insert( r->data.data(), r->pos, r->dataSize );
734 }
735 break;
736
737 case UndoRec::DELTEXT:
738 {
739 EditString& str = text.Get( r->line );
740 str.Delete( r->pos, r->dataSize );
741 }
742 break;
743
744 case UndoRec::DELLINE:
745 {
746 int n = r->line;
747 text.Delete( n, 1 );
748 }
749 break;
750
751 case UndoRec::ADDLINE:
752 {
753 int n = r->line;
754 text.Insert( n, 1, r->attr );
755 text.Get( n ).Set( r->data.data(), r->dataSize );
756 }
757 break;
758
759 default:
760 NCMessageBox( ( NCDialogParent* )Parent(), "bad oper", "Redo", true );
761 undoList.Clear();
762 return false;
763 }
764 }
765
766 cursor = u->endCursor;
767 marker = u->endMarker;
768 _changed = chg;
769 }
770 catch ( ... )
771 {
772 undoList.Clear();
773 throw;
774 }
775
776 CursorToScreen();
777 CalcScroll();
778 SendChanges();
779 Refresh();
780
781
782 return true;
783 }
784
InsChar(unicode_t ch)785 void EditWin::InsChar( unicode_t ch ) //!Undo
786 {
787 char buf[0x100];
788 int n = charset->SetChar( buf, ch );
789
790 if ( n <= 0 )
791 {
792 return;
793 }
794
795 clPtr<UndoBlock> undoBlock = new UndoBlock( true, _changed );
796 undoBlock->SetBeginPos( cursor, marker );
797
798 try
799 {
800
801 SetChanged( cursor.line );
802 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
803 EditString& str = text.Get( cursor.line );
804 str.Insert( buf, cursor.pos, n );
805 undoBlock->InsText( cursor.line, cursor.pos, buf, n );
806
807 cursor.pos += n;
808 SendChanges();
809 marker = cursor;
810
811 undoBlock->SetEndPos( cursor, marker );
812 undoList.Append( undoBlock );
813
814 }
815 catch ( ... )
816 {
817 undoList.Clear();
818 throw;
819 }
820
821 CursorToScreen();
822 CalcScroll();
823 SendChanges();
824 Refresh();
825 }
826
DelMarked()827 bool EditWin::DelMarked() //!Undo
828 {
829 if ( cursor == marker ) { return false; }
830
831 clPtr<UndoBlock> undoBlock = new UndoBlock( false, _changed );
832 undoBlock->SetBeginPos( cursor, marker );
833
834 EditPoint begin, end;
835
836 if ( cursor < marker )
837 {
838 begin = cursor;
839 end = marker;
840 }
841 else
842 {
843 begin = marker;
844 end = cursor;
845 }
846
847 SetChanged( begin.line );
848
849 try
850 {
851
852 if ( begin.line == end.line )
853 {
854 EditString& line = text.Get( begin.line );
855 int count = end.pos - begin.pos;
856 undoBlock->DelText( begin.line, begin.pos, line.Get() + begin.pos, count );
857 line.Delete( begin.pos, count );
858 cursor = begin;
859 }
860 else
861 {
862 EditString& bLine = text.Get( begin.line );
863 EditString& eLine = text.Get( end.line );
864
865 if ( begin.pos < bLine.len )
866 {
867 undoBlock->DelText( begin.line, begin.pos, bLine.Get() + begin.pos, bLine.len - begin.pos );
868 bLine.Delete( begin.pos, bLine.len - begin.pos );
869 }
870
871 if ( end.pos < eLine.len )
872 {
873 int count = eLine.len - end.pos;
874 bLine.Insert( eLine.Get() + end.pos, begin.pos, count );
875 undoBlock->InsText( begin.line, begin.pos, bLine.Get() + begin.pos, count );
876 }
877
878 undoBlock->Attr( begin.line, bLine.flags, eLine.flags );
879 bLine.flags = eLine.flags;
880
881 int delCount = end.line - begin.line;
882
883 for ( int i = 0; i < delCount; i++ )
884 {
885 EditString& line = text.Get( begin.line + i + 1 );
886 undoBlock->DelLine( begin.line + 1 /*!!! без i*/, line.flags, line.Get(), line.Len() );
887 }
888
889 text.Delete( begin.line + 1, delCount );
890 cursor = begin;
891 }
892
893 marker = cursor;
894
895 undoBlock->SetEndPos( cursor, marker );
896 undoList.Append( undoBlock );
897
898 CursorToScreen();
899 CalcScroll();
900 SendChanges();
901 Refresh();
902
903 }
904 catch ( ... )
905 {
906 undoList.Clear();
907 throw;
908 }
909
910 return true;
911 }
912
_ToClipboardText(char * s,int count,charset_struct * cs,ClipboardText & ctx)913 inline void _ToClipboardText( char* s, int count, charset_struct* cs, ClipboardText& ctx )
914 {
915 if ( count <= 0 )
916 {
917 //printf("??? count= %i\n", count);
918 return;
919 }
920
921 char* endPos = s + count;
922
923 while ( s )
924 {
925 //bool tab;
926 unicode_t c = cs->GetChar( s, endPos );
927 ctx.Append( c );
928 s = cs->GetNext( s, endPos );
929 }
930 }
931
ToClipboard()932 void EditWin::ToClipboard()
933 {
934 if ( cursor == marker ) { return; }
935
936 ClipboardText ctx;
937
938 EditPoint begin, end;
939
940 if ( cursor < marker )
941 {
942 begin = cursor;
943 end = marker;
944 }
945 else
946 {
947 begin = marker;
948 end = cursor;
949 }
950
951 if ( begin.line == end.line )
952 {
953 EditString& line = text.Get( begin.line );
954 _ToClipboardText( line.Get() + begin.pos, end.pos - begin.pos, charset, ctx );
955 //cursor = begin;
956 }
957 else
958 {
959 EditString& bLine = text.Get( begin.line );
960 _ToClipboardText( bLine.Get() + begin.pos, bLine.len - begin.pos, charset, ctx );
961 ctx.Append( '\n' );
962
963 for ( int i = begin.line + 1; i < end.line; i++ )
964 {
965 EditString& line = text.Get( i );
966 _ToClipboardText( line.Get(), line.len, charset, ctx );
967 ctx.Append( '\n' );
968 }
969
970 // EditString& eLine = text.Get( end.line );
971
972 if ( end.pos > 0 )
973 {
974 EditString& eLine = text.Get( end.line );
975 _ToClipboardText( eLine.Get(), end.pos, charset, ctx );
976 }
977 }
978
979 ClipboardSetText( this, ctx );
980 }
981
FromClipboard()982 void EditWin::FromClipboard() //!Undo
983 {
984 ClipboardText ctx;
985 ClipboardGetText( this, &ctx );
986 int ctxLen = ctx.Count();
987
988 if ( ctxLen <= 0 ) { return; }
989
990 clPtr<UndoBlock> undoBlock = new UndoBlock( false, _changed );
991 undoBlock->SetBeginPos( cursor, marker );
992
993 try
994 {
995
996 recomendedCursorCol = -1;
997 SetChanged( cursor.line );
998
999 int ctxPos = 0;
1000
1001 // insert clipboard text (ctx) into editor buffer (text) line by line
1002 while ( ctxPos < ctxLen )
1003 {
1004 char buf[1024];
1005 int bufPos = 0;
1006 bool newline = false;
1007
1008 // find next newline char
1009 for ( ; ctxPos < ctxLen && bufPos < 1024 - 32; ctxPos++ )
1010 {
1011 unicode_t ch = ctx[ctxPos];
1012
1013 if ( ch == '\n' )
1014 {
1015 newline = true;
1016 ctxPos++;
1017 break;
1018 }
1019
1020 bufPos += charset->SetChar( buf + bufPos, ch );
1021 }
1022
1023 EditString& line = text.Get( cursor.line );
1024
1025 if ( bufPos > 0 ) // insert clipboard fragment up to newline to cursor pos
1026 {
1027 line.Insert( buf, cursor.pos, bufPos );
1028 undoBlock->InsText( cursor.line, cursor.pos, buf, bufPos );
1029 }
1030
1031 cursor.pos += bufPos;
1032
1033 if ( newline ) // then we need to add new line to edit buffer
1034 {
1035 EditString& str = text.Get( cursor.line );
1036 text.Insert( cursor.line + 1, 1, line.flags );
1037
1038 if ( cursor.pos < str.len ) // move original text that was after cursor on current line to a new line
1039 {
1040 char* textAfterCursor = str.Get() + cursor.pos;
1041 int lenTextAfterCursor = str.len - cursor.pos;
1042 undoBlock->AddLine( cursor.line + 1, line.flags, textAfterCursor, lenTextAfterCursor );
1043 // copy the aftercursor text to new line
1044 text.Get( cursor.line + 1 ).Set( textAfterCursor, lenTextAfterCursor );
1045 // remove the aftercursor text from current line
1046 str.len = cursor.pos;
1047 undoBlock->DelText( cursor.line, cursor.pos, textAfterCursor, lenTextAfterCursor );
1048 }
1049 else // we have added an empty line
1050 {
1051 undoBlock->AddLine( cursor.line + 1, line.flags, 0, 0 );
1052 }
1053
1054 cursor.line++;
1055 cursor.pos = 0;
1056 }
1057 }
1058
1059 marker = cursor;
1060
1061 undoBlock->SetEndPos( cursor, marker );
1062 undoList.Append( undoBlock );
1063
1064 CalcScroll();
1065 CursorToScreen();
1066 SendChanges();
1067 Refresh();
1068
1069 }
1070 catch ( ... )
1071 {
1072 undoList.Clear();
1073 throw;
1074 }
1075 }
1076
Cut()1077 void EditWin::Cut()
1078 {
1079 if ( cursor == marker ) { return; }
1080
1081 ToClipboard();
1082 DelMarked();
1083 }
1084
Del(bool DeleteWord)1085 void EditWin::Del( bool DeleteWord ) //!Undo
1086 {
1087 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
1088 ASSERT( cursor.pos >= 0 && cursor.pos <= text.Get( cursor.line ).Len() );
1089
1090 if ( DelMarked() )
1091 {
1092 return;
1093 }
1094
1095 clPtr<UndoBlock> undoBlock = new UndoBlock( true, _changed );
1096 undoBlock->SetBeginPos( cursor, marker );
1097
1098 try
1099 {
1100 EditString& str = text.Get( cursor.line );
1101
1102 if ( cursor.pos < str.len )
1103 {
1104 SetChanged( cursor.line );
1105
1106 char* s = str.Get() + cursor.pos;
1107 char* end = str.Get() + str.Len();
1108
1109 int totalDelCount = 0;
1110
1111 if ( DeleteWord )
1112 {
1113 EditPoint oldcursor = cursor;
1114 EditPoint p = cursor;
1115
1116 if ( p.line < 0 || p.line >= text.Count() ) { return; }
1117
1118 if ( p.pos < 0 || p.pos > text.Get( p.line ).Len() ) { return; }
1119
1120 EditString& str = text.Get( p.line );
1121 unicode_t c = str.Len() > 0 ? charset->GetChar( str.Get() + p.pos, str.Get() + str.Len() ) : ' ';
1122
1123 int group = EditBuf::GetCharGroup( c );
1124
1125 while ( StepRight( &p, &c ) )
1126 {
1127 cursor = p;
1128
1129 if ( EditBuf::GetCharGroup( c ) != group ) { break; }
1130 }
1131
1132 totalDelCount = cursor.pos - oldcursor.pos;
1133
1134 cursor = oldcursor;
1135 }
1136 else
1137 {
1138 char* t = charset->GetNext( s, end );
1139 int delCount = t ? t - s : str.len - cursor.pos;
1140
1141 totalDelCount += delCount;
1142 }
1143
1144 undoBlock->DelText( cursor.line, cursor.pos, s, totalDelCount );
1145
1146 str.Delete( cursor.pos, totalDelCount );
1147 }
1148 else
1149 {
1150 if ( cursor.line + 1 < text.Count() )
1151 {
1152 SetChanged( cursor.line );
1153
1154 EditString& str_1 = text.Get( cursor.line + 1 );
1155
1156 str.Insert( str_1.Get(), cursor.pos, str_1.len );
1157 undoBlock->InsText( cursor.line, cursor.pos, str_1.Get(), str_1.len );
1158
1159 undoBlock->Attr( cursor.line, str.flags, str_1.flags );
1160 str.flags = str_1.flags;
1161
1162 undoBlock->DelLine( cursor.line + 1, str_1.flags, str_1.Get(), str_1.len );
1163 text.Delete( cursor.line + 1, 1 );
1164 }
1165 }
1166
1167 marker = cursor;
1168
1169 undoBlock->SetEndPos( cursor, marker );
1170 undoList.Append( undoBlock );
1171
1172 CalcScroll();
1173 SendChanges();
1174 Refresh();
1175
1176 }
1177 catch ( ... )
1178 {
1179 undoList.Clear();
1180 throw;
1181 }
1182
1183 }
1184
Backspace(bool DeleteWord)1185 void EditWin::Backspace( bool DeleteWord ) //!Undo
1186 {
1187 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
1188 ASSERT( cursor.pos >= 0 && cursor.pos <= text.Get( cursor.line ).Len() );
1189
1190 recomendedCursorCol = -1;
1191
1192 if ( DelMarked() )
1193 {
1194 return;
1195 }
1196
1197 clPtr<UndoBlock> undoBlock = new UndoBlock( true, _changed );
1198 undoBlock->SetBeginPos( cursor, marker );
1199
1200 try
1201 {
1202
1203 EditString& str = text.Get( cursor.line );
1204
1205 if ( cursor.pos > 0 )
1206 {
1207 SetChanged( cursor.line );
1208
1209 if ( DeleteWord )
1210 {
1211 EditPoint oldcursor = cursor;
1212 EditPoint p = cursor;
1213 unicode_t c;
1214
1215 if ( !StepLeft( &p, &c ) ) { return; }
1216
1217 int group = EditBuf::GetCharGroup( c );
1218 cursor = p;
1219
1220 while ( StepLeft( &p, &c ) && EditBuf::GetCharGroup( c ) == group )
1221 {
1222 if ( cursor.line == p.line )
1223 {
1224 cursor = p;
1225 }
1226 else
1227 {
1228 // just stay at the beginning of this line
1229 cursor.pos = 0;
1230 break;
1231 }
1232 }
1233
1234 int totalDelCount = oldcursor.pos - cursor.pos;
1235
1236 char* s = str.Get() + cursor.pos;
1237
1238 undoBlock->DelText( cursor.line, cursor.pos, s, totalDelCount );
1239
1240 str.Delete( cursor.pos, totalDelCount );
1241 }
1242 else
1243 {
1244 char* s = str.Get() + cursor.pos;
1245 char* t = charset->GetPrev( s, str.Get() );
1246
1247 if ( t )
1248 {
1249 undoBlock->DelText( cursor.line, t - str.Get(), t, s - t );
1250 str.Delete( t - str.Get(), s - t );
1251 cursor.pos -= s - t;
1252 }
1253 else
1254 {
1255 undoBlock->DelText( cursor.line, 0, str.Get(), cursor.pos );
1256 str.Delete( 0, cursor.pos );
1257 cursor.pos = 0;
1258 }
1259 }
1260 }
1261 else
1262 {
1263 if ( cursor.line > 0 )
1264 {
1265 SetChanged( cursor.line - 1 );
1266 EditString& str_1 = text.Get( cursor.line - 1 );
1267 int l = str_1.len;
1268
1269
1270 undoBlock->InsText( cursor.line - 1, str_1.len, str.Get(), str.Len() ); //пока не поменялся str_1.len
1271 str_1.Insert( str.Get(), str_1.len, str.len );
1272
1273 undoBlock->Attr( cursor.line - 1, str_1.flags, str.flags );
1274 str_1.flags = str.flags;
1275
1276 undoBlock->DelLine( cursor.line, str.flags, str.Get(), str.Len() );
1277 text.Delete( cursor.line, 1 );
1278
1279 cursor.line--;
1280 cursor.pos = l;
1281 }
1282 }
1283
1284 marker = cursor;
1285
1286 undoBlock->SetEndPos( cursor, marker );
1287 undoList.Append( undoBlock );
1288
1289 CursorToScreen();
1290 SendChanges();
1291 Refresh();
1292
1293 }
1294 catch ( ... )
1295 {
1296 undoList.Clear();
1297 throw;
1298 }
1299
1300 }
1301
Ident(EditString & str)1302 char* EditWin::Ident( EditString& str )
1303 {
1304 if ( !str.len )
1305 {
1306 return 0;
1307 }
1308
1309 char* s = str.Get();
1310 char* end = s + str.len;
1311
1312 while ( true )
1313 {
1314 unicode_t c = charset->GetChar( s, end );
1315
1316 if ( c != ' ' && c != '\t' )
1317 {
1318 break;
1319 }
1320
1321 //bool tab;
1322 s = charset->GetNext( s, end );
1323
1324 if ( !s )
1325 {
1326 return 0;
1327 }
1328 }
1329
1330 return s;
1331 }
1332
SetCharset(charset_struct * cs)1333 void EditWin::SetCharset( charset_struct* cs )
1334 {
1335 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
1336 ASSERT( cursor.pos >= 0 && cursor.pos <= text.Get( cursor.line ).Len() );
1337 charset = cs;
1338 CursorRight( false );
1339 CursorLeft( false );
1340 SendChanges();
1341 marker = cursor;
1342 EnableShl( g_WcmConfig.editShl );
1343 Refresh();
1344 }
1345
DeleteLine()1346 void EditWin::DeleteLine() //!Undo
1347 {
1348 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
1349 ASSERT( cursor.pos >= 0 && cursor.pos <= text.Get( cursor.line ).Len() );
1350 recomendedCursorCol = -1;
1351
1352 clPtr<UndoBlock> undoBlock = new UndoBlock( false, _changed );
1353 undoBlock->SetBeginPos( cursor, marker );
1354
1355 EditString& str = text.Get( cursor.line );
1356
1357 try
1358 {
1359 if ( cursor.line + 1 >= text.Count() )
1360 {
1361 if ( str.len == 0 )
1362 {
1363 return;
1364 }
1365
1366 undoBlock->DelText( cursor.line, 0, str.Get(), str.len );
1367 str.len = 0; //!!!
1368 cursor.pos = 0;
1369 }
1370 else
1371 {
1372 undoBlock->DelLine( cursor.line, str.flags, str.Get(), str.len );
1373 text.Delete( cursor.line, 1 );
1374 cursor.pos = 0;
1375 }
1376
1377 SetChanged( cursor.line - 1 );
1378
1379 marker = cursor;
1380
1381 undoBlock->SetEndPos( cursor, marker );
1382 undoList.Append( undoBlock );
1383
1384 CursorToScreen();
1385 SendChanges();
1386 Refresh();
1387 }
1388 catch ( ... )
1389 {
1390 undoList.Clear();
1391 throw;
1392 }
1393 }
1394
Enter()1395 void EditWin::Enter() //!Undo
1396 {
1397 ASSERT( cursor.line >= 0 && cursor.line < text.Count() );
1398 ASSERT( cursor.pos >= 0 && cursor.pos <= text.Get( cursor.line ).Len() );
1399
1400 recomendedCursorCol = -1;
1401
1402 clPtr<UndoBlock> undoBlock = new UndoBlock( true, _changed );
1403 undoBlock->SetBeginPos( cursor, marker );
1404
1405 try
1406 {
1407 SetChanged( cursor.line );
1408
1409 EditString& str = text.Get( cursor.line );
1410 text.Insert( cursor.line + 1, 1, str.flags );
1411
1412 if ( cursor.pos < str.len )
1413 {
1414 text.Get( cursor.line + 1 ).Set( str.Get() + cursor.pos, str.len - cursor.pos );
1415 undoBlock->AddLine( cursor.line + 1, str.flags, str.Get() + cursor.pos, str.len - cursor.pos );
1416 undoBlock->DelText( cursor.line, cursor.pos, str.Get() + cursor.pos, str.len - cursor.pos );
1417 str.len = cursor.pos;
1418 }
1419 else
1420 {
1421 undoBlock->AddLine( cursor.line + 1, str.flags, 0, 0 );
1422 }
1423
1424 cursor.line++;
1425 cursor.pos = 0;
1426
1427 if ( autoIdent )
1428 {
1429 for ( int i = cursor.line - 1; i >= 0; i-- )
1430 {
1431 char* s = Ident( text.Get( i ) );
1432
1433 if ( s )
1434 {
1435 char* p = text.Get( i ).Get();
1436 EditString& cstr = text.Get( cursor.line );
1437 char* t = Ident( cstr );
1438
1439 if ( t )
1440 {
1441 undoBlock->DelText( cursor.line, 0, cstr.Get() , t - cstr.Get() );
1442 cstr.Delete( 0, t - cstr.Get() );
1443 cursor.pos = 0;
1444 }
1445
1446 undoBlock->InsText( cursor.line, 0, p, s - p );
1447 cstr.Insert( p, 0, s - p );
1448 cursor.pos = s - p;
1449 break;
1450 }
1451 }
1452 }
1453
1454 marker = cursor;
1455
1456 undoBlock->SetEndPos( cursor, marker );
1457 undoList.Append( undoBlock );
1458
1459 CursorToScreen();
1460 SendChanges();
1461 Refresh();
1462
1463 }
1464 catch ( ... )
1465 {
1466 undoList.Clear();
1467 throw;
1468 }
1469
1470 }
1471
GetScrollCtx() const1472 sEditorScrollCtx EditWin::GetScrollCtx() const
1473 {
1474 sEditorScrollCtx Ctx;
1475 Ctx.m_Point = this->GetCursorPos();
1476 Ctx.m_FirstLine = firstLine;
1477 return Ctx;
1478 }
1479
SetScrollCtx(const sEditorScrollCtx & Ctx)1480 void EditWin::SetScrollCtx( const sEditorScrollCtx& Ctx )
1481 {
1482 recomendedCursorCol = -1;
1483 int MaxLine = std::max( 0, text.Count() - rows );
1484 SetCursorPos( Ctx.m_Point );
1485 firstLine = Ctx.m_FirstLine;
1486 firstLine = std::min( firstLine, MaxLine );
1487 colOffset = 0;
1488 marker = cursor;
1489 SendChanges();
1490 Refresh();
1491 }
1492
CalcScroll()1493 void EditWin::CalcScroll()
1494 {
1495 ScrollInfo vsi;
1496 vsi.m_PageSize = rows;
1497 vsi.m_Size = text.Count();
1498 vsi.m_Pos = firstLine;
1499 bool vVisible = vscroll.IsVisible();
1500 vscroll.Command( CMD_SCROLL_INFO, SCMD_SCROLL_VCHANGE, this, &vsi );
1501
1502 if ( vVisible != vscroll.IsVisible() )
1503 {
1504 this->RecalcLayouts();
1505 }
1506 }
1507
1508
Command(int id,int subId,Win * win,void * data)1509 bool EditWin::Command( int id, int subId, Win* win, void* data )
1510 {
1511 if ( id != CMD_SCROLL_INFO )
1512 {
1513 return false;
1514 }
1515
1516 int n = firstLine;
1517
1518 switch ( subId )
1519 {
1520 case SCMD_SCROLL_LINE_UP:
1521 n--;
1522 break;
1523
1524 case SCMD_SCROLL_LINE_DOWN:
1525 n++;
1526 break;
1527
1528 case SCMD_SCROLL_PAGE_UP:
1529 n -= rows;
1530 break;
1531
1532 case SCMD_SCROLL_PAGE_DOWN:
1533 n += rows;
1534 break;
1535
1536 case SCMD_SCROLL_TRACK:
1537 n = ( ( int* )data )[0];
1538 break;
1539 }
1540
1541 if ( n + rows > text.Count() )
1542 {
1543 n = text.Count() - rows;
1544 }
1545
1546 if ( n < 0 ) { n = 0; }
1547
1548 if ( n != firstLine )
1549 {
1550 firstLine = n;
1551 CalcScroll();
1552 SendChanges();
1553 Refresh();
1554 }
1555
1556 return true;
1557 }
1558
Broadcast(int id,int subId,Win * win,void * data)1559 bool EditWin::Broadcast( int id, int subId, Win* win, void* data )
1560 {
1561 if ( id == ID_CHANGED_CONFIG_BROADCAST )
1562 {
1563 autoIdent = g_WcmConfig.editAutoIdent;
1564 tabSize = g_WcmConfig.editTabSize;
1565
1566 if ( IsVisible() ) { Invalidate(); }
1567
1568 return true;
1569 }
1570
1571 return false;
1572 }
1573
1574
ColorById(int id)1575 unsigned EditWin::ColorById( int id )
1576 {
1577 switch ( id )
1578 {
1579 case COLOR_DEF_ID:
1580 return shlDEF;
1581
1582 case COLOR_KEYWORD_ID:
1583 return shlKEYWORD;
1584
1585 case COLOR_COMMENT_ID:
1586 return shlCOMMENT;
1587
1588 case COLOR_STRING_ID:
1589 return shlSTRING;
1590
1591 case COLOR_PRE_ID:
1592 return shlPRE;
1593
1594 case COLOR_NUM_ID:
1595 return shlNUM;
1596
1597 case COLOR_OPER_ID:
1598 return shlOPER;
1599
1600 case COLOR_ATTN_ID:
1601 return shlATTN;
1602 }
1603
1604 //printf("color id ?(%i)\n", id);
1605 return shlDEF;
1606 }
1607
1608 #ifdef _WIN32
1609 #include "w32util.h"
1610 #endif
1611
CheckAsciiSymbol(charset_struct * cs,unsigned char c)1612 static bool CheckAsciiSymbol( charset_struct* cs, unsigned char c )
1613 {
1614 char buf[64];
1615 int n = cs->SetChar( buf, c );
1616 return n == 1 && buf[0] == c;
1617 }
1618
CheckAscii(charset_struct * cs)1619 static bool CheckAscii( charset_struct* cs )
1620 {
1621 for ( int i = 1; i < 128; i++ )
1622 if ( !CheckAsciiSymbol( cs, i ) )
1623 {
1624 return false;
1625 }
1626
1627 return true;
1628 }
1629
EnableShl(bool on)1630 void EditWin::EnableShl( bool on )
1631 {
1632 _shl = 0;
1633 _shlLine = -1;
1634 _shlConf = 0;
1635
1636 if ( on )
1637 {
1638
1639 if ( !CheckAscii( charset ) )
1640 {
1641 return;
1642 }
1643
1644 std::unordered_map< std::string, int > colors;
1645 colors["DEF" ] = COLOR_DEF_ID;
1646 colors["KEYWORD"] = COLOR_KEYWORD_ID;
1647 colors["COMMENT"] = COLOR_COMMENT_ID;
1648 colors["STRING" ] = COLOR_STRING_ID;
1649 colors["PRE" ] = COLOR_PRE_ID;
1650 colors["NUM" ] = COLOR_NUM_ID;
1651 colors["OPER" ] = COLOR_OPER_ID;
1652 colors["ATTN" ] = COLOR_ATTN_ID;
1653
1654 std::vector<char> firstLine;
1655
1656 if ( text.Count() > 0 )
1657 {
1658 EditString& str = text.Get( EditList::Pos() );
1659 int len = str.len;
1660
1661 firstLine.resize( len + 1 );
1662
1663 char* s = firstLine.data();
1664
1665 if ( len > 0 )
1666 {
1667 memcpy( firstLine.data(), str.Get(), len );
1668 }
1669
1670 firstLine[len] = 0;
1671
1672 char* ns = 0;
1673
1674 for ( ; *s; s++ )
1675 if ( *s <= 0 || *s > ' ' )
1676 {
1677 ns = s;
1678 }
1679
1680 if ( ns ) { ns[1] = 0; }
1681 }
1682
1683 _shlConf = new SHL::ShlConf();
1684 #ifdef _WIN32
1685 std::vector<wchar_t> path = GetAppPath();
1686 _shlConf->Parze( carray_cat<wchar_t>( GetAppPath().data(), utf8_to_sys( "\\shl\\config.cfg" ).data() ).data() );
1687 #else
1688 _shlConf->Parze( ( sys_char_t* ) UNIX_CONFIG_DIR_PATH "/shl/config.cfg" );
1689 #endif
1690 _shlLine = -1;
1691 //надо сделать не utf8 а текущий cs
1692 _shl = _shlConf->Get( _path.GetUnicode() , utf8_to_unicode( firstLine.data() ).data(), colors );
1693 }
1694
1695 __RefreshScreenData();
1696 Invalidate();
1697 }
1698
Load(clPtr<FS> fs,FSPath & path,MemFile & f)1699 void EditWin::Load( clPtr<FS> fs, FSPath& path, MemFile& f )
1700 {
1701 Clear();
1702 text.Load( f );
1703 _fs = fs;
1704 _path = path;
1705 CalcScroll();
1706
1707 _changed = false;
1708
1709 EnableShl( g_WcmConfig.editShl );
1710 }
1711
Clear()1712 void EditWin::Clear()
1713 {
1714 text.Clear();
1715 undoList.Clear();
1716 cursor.Set( 0, 0 );
1717 marker = cursor;
1718 firstLine = 0;
1719 colOffset = 0;
1720 _path.Clear();
1721 _fs = 0;
1722 recomendedCursorCol = -1;
1723 }
1724
Save(MemFile & f)1725 void EditWin::Save( MemFile& f )
1726 {
1727 f.Clear();
1728 text.Save( f );
1729 if ( g_WcmConfig.editClearHistoryAfterSaving ) undoList.Clear();
1730 // changed = false;
1731 }
1732
SetChanged(int minLine)1733 void EditWin::SetChanged( int minLine )
1734 {
1735 _changed = true;
1736
1737 if ( _shlLine > minLine ) { _shlLine = minLine; }
1738 }
1739
RefreshShl(int n)1740 void EditWin::RefreshShl( int n )
1741 {
1742 if ( _shl && n > _shlLine && text.Count() > 0 )
1743 {
1744 int first = _shlLine;
1745
1746 int count = text.Count();
1747
1748 if ( first < 0 )
1749 {
1750 text.Get( 0 ).shlId = _shl->GetStartId();
1751 first = 0;
1752 _shlLine = 0;
1753 }
1754
1755 int last = n;
1756
1757 if ( last >= count ) { last = count - 1; }
1758
1759 if ( first < last )
1760 {
1761 EditList::Pos pos( first );
1762 int statId = text.Get( pos ).shlId;
1763
1764 for ( ; pos <= last ; pos.Inc() )
1765 {
1766 EditString& str = text.Get( pos );
1767 char* begin = str.Get(), *s = begin, *end = s + str.Len();
1768
1769 if ( pos != first ) { str.shlId = statId; }
1770
1771 if ( pos != last )
1772 {
1773 statId = _shl->ScanLine( ( unsigned char* )begin, ( unsigned char* )end, statId );
1774 }
1775 }
1776 }
1777
1778 _shlLine = last;
1779 }
1780 }
1781
__RefreshScreenData()1782 void EditWin::__RefreshScreenData()
1783 {
1784 if ( screen.Rows() <= 0 || screen.Cols() <= 0 ) { return; }
1785
1786 //EditorColors colors = *editorColors;
1787
1788 int r;
1789
1790 for ( r = 0; r < screen.Rows(); r++ )
1791 {
1792 int line = r + firstLine;
1793
1794 if ( line < 0 || line >= text.Count() )
1795 {
1796 screen.Set( r, 0, screen.Cols(), ' ', 0, color_background );
1797 continue;
1798 }
1799
1800 EditString& str = text.Get( line );
1801 char* begin = str.Get(), *s = begin, *end = s + str.Len();
1802 bool tab = charset->IsTab( s, end );
1803 int col = 0;
1804
1805 if ( str.len )
1806 {
1807
1808 //TEMP
1809 std::vector<char> colId( str.len + 1 );
1810 memset( colId.data(), -1, str.len + 1 );
1811
1812 if ( _shl )
1813 {
1814 RefreshShl( line );
1815 _shl->ScanLine( ( unsigned char* )str.Get(), colId.data(), str.len, str.shlId );
1816 }
1817
1818 int ce = col;
1819
1820 while ( s )
1821 {
1822 ce = ( tab ) ? col + tabSize - col % tabSize : col + 1;
1823
1824 if ( ce > colOffset ) { break; }
1825
1826 s = charset->GetNext( s, end );
1827 tab = charset->IsTab( s, end );
1828 col = ce;
1829 }
1830
1831 while ( s && col - colOffset < screen.Cols() )
1832 {
1833 bool marked = InMark( EditPoint( line, s - begin ) );
1834
1835 if ( s >= end )
1836 {
1837 printf( "s>=end (%i)\n", int( s - end ) );
1838 }
1839
1840 unsigned COL = _shl ? ColorById( colId[s - begin] ) : color_text;
1841
1842 if ( tab )
1843 {
1844 ce = col + tabSize - col % tabSize;
1845
1846
1847 screen.Set( r, col - colOffset, ce, ' ', 0, marked ? color_mark_background : color_background );
1848 col = ce;
1849 }
1850 else
1851 {
1852 unicode_t ch = charset->GetChar( s, end );
1853 screen.Set( r, col - colOffset, col - colOffset + 1, ( ch < 32 /*|| ch>=0x80 && ch< 0xA0*/ ) ? '.' : ch,
1854 ( ch < 32 /*|| ch>=0x80 && ch< 0xA0*/ ) ? 0xFF3030 : ( marked ? color_mark_text : /*colors.fg*/ COL ),
1855 marked ? color_mark_background : color_background );
1856 col++;
1857 }
1858
1859 s = charset->GetNext( s, end );
1860 tab = charset->IsTab( s, end );
1861 }
1862 }
1863
1864 if ( col - colOffset < screen.Cols() )
1865 {
1866 screen.Set( r, col - colOffset, screen.Cols(), ' ', 0, InMark( EditPoint( line, end - begin ) ) ? color_mark_background : color_background );
1867 }
1868 }
1869
1870 screen.SetCursor( cursor.line - firstLine, GetCursorCol() - colOffset );
1871 }
1872
1873
1874 #define PBSIZE (0x100)
1875
__DrawChanges()1876 void EditWin::__DrawChanges()
1877 {
1878 if ( screen.Rows() <= 0 && screen.Cols() <= 0 ) { return; }
1879
1880 wal::GC gc( this );
1881 gc.Set( GetFont() );
1882
1883 if ( screen.prevCursor != screen.cursor &&
1884 screen.prevCursor.line >= 0 && screen.prevCursor.line < screen.Rows() &&
1885 screen.prevCursor.pos >= 0 && screen.prevCursor.pos < screen.Cols() )
1886 {
1887 screen.Line( screen.prevCursor.line )[screen.prevCursor.pos].changed = true;
1888 }
1889
1890 for ( int r = 0; r < screen.Rows(); r++ )
1891 {
1892 int c = 0;
1893 EditScreenChar* p = screen.Line( r );
1894
1895 if ( !p ) { continue; }
1896
1897 EditScreenChar* pe = p + screen.Cols();
1898 int y = editRect.top + r * charH;
1899
1900 while ( p < pe )
1901 {
1902 if ( !p->changed )
1903 {
1904 while ( p < pe && !p->changed ) { p++; c++; }
1905
1906 continue;
1907 }
1908
1909 int x = editRect.left + c * charW;
1910
1911 if ( p->ch == ' ' )
1912 {
1913 EditScreenChar* t = p + 1;
1914 p->changed = false;
1915
1916 for ( ; t < pe && t->ch == ' ' && t->changed && t->bColor == p->bColor; t++ )
1917 {
1918 t->changed = false;
1919 }
1920
1921 int n = t - p;
1922 gc.SetFillColor( p->bColor );
1923 gc.FillRect( crect( x, y, x + n * charW, y + charH ) );
1924 p = t;
1925 c += n;
1926 continue;
1927 }
1928
1929 EditScreenChar* t = p + 1;
1930 p->changed = false;
1931
1932 for ( ; t < pe && t->changed && t->bColor == p->bColor && t->fColor == p->fColor; t++ )
1933 {
1934 t->changed = false;
1935 }
1936
1937 int n = t - p;
1938 gc.SetFillColor( p->bColor );
1939 gc.SetTextColor( p->fColor );
1940
1941 while ( n > 0 )
1942 {
1943 unicode_t buf[PBSIZE];
1944 int count = n > PBSIZE ? PBSIZE : n;
1945
1946 for ( int i = 0; i < count; i++ ) { buf[i] = p[i].ch; }
1947
1948 gc.TextOutF( x, y, buf, count );
1949 n -= count;
1950 p += count;
1951 x += count * charW;
1952 c += count;
1953 }
1954 }
1955 }
1956
1957
1958 //перерисовать курсор всегда // if (screen.prevCursor != screen.cursor)
1959 DrawCursor( gc );
1960 }
1961
DrawCursor(wal::GC & gc)1962 void EditWin::DrawCursor( wal::GC& gc )
1963 {
1964 int curR = screen.cursor.line;
1965 int curC = screen.cursor.pos;
1966
1967 if ( curR >= 0 && curR < screen.Rows() && curC >= 0 && curC < screen.Cols() )
1968 {
1969 int y = editRect.top + curR * charH;
1970 int x = editRect.left + curC * charW;
1971 gc.SetFillColor( color_cursor/*0xFFFF00*/ );
1972 gc.FillRectXor( GetCursorRect( x, y ) );
1973 }
1974
1975 screen.prevCursor = screen.cursor;
1976 }
1977
Paint(wal::GC & gc,const crect & paintRect)1978 void EditWin::Paint( wal::GC& gc, const crect& paintRect )
1979 {
1980 int r1 = ( paintRect.top - editRect.top ) / charH;
1981 int r2 = ( paintRect.bottom - editRect.top + charH - 1 ) / charH;
1982 int c1 = ( paintRect.left - editRect.left ) / charW;
1983 int c2 = ( paintRect.right - editRect.left + charW - 1 ) / charW;
1984
1985 if ( r1 < 0 ) { r1 = 0; }
1986
1987 if ( r2 > screen.Rows() ) { r2 = screen.Rows(); }
1988
1989 if ( c1 < 0 ) { c1 = 0; }
1990
1991 if ( c2 > screen.Cols() ) { c2 = screen.Cols(); }
1992
1993 if ( r1 >= r2 || c1 >= c2 ) { return; }
1994
1995 gc.Set( GetFont() );
1996
1997 for ( int r = r1; r < r2; r++ )
1998 {
1999 int c = c1;
2000 EditScreenChar* p = screen.Line( r ) + c;
2001
2002 if ( !p ) { continue; }
2003
2004 EditScreenChar* pe = p + c2 - c1;
2005 int y = editRect.top + r * charH;
2006
2007 while ( p < pe )
2008 {
2009 int x = editRect.left + c * charW;
2010
2011 if ( p->ch == ' ' )
2012 {
2013 EditScreenChar* t = p + 1;
2014 p->changed = false;
2015
2016 for ( ; t < pe && t->ch == ' ' && t->bColor == p->bColor; t++ )
2017 {
2018 t->changed = false;
2019 }
2020
2021 int n = t - p;
2022 gc.SetFillColor( p->bColor );
2023 gc.FillRect( crect( x, y, x + n * charW, y + charH ) );
2024 p = t;
2025 c += n;
2026 continue;
2027 }
2028
2029 EditScreenChar* t = p + 1;
2030 p->changed = false;
2031
2032 for ( ; t < pe && t->bColor == p->bColor && t->fColor == p->fColor; t++ )
2033 {
2034 t->changed = false;
2035 }
2036
2037 int n = t - p;
2038 gc.SetFillColor( p->bColor );
2039 gc.SetTextColor( p->fColor );
2040
2041 while ( n > 0 )
2042 {
2043 unicode_t buf[PBSIZE];
2044 int count = n > PBSIZE ? PBSIZE : n;
2045
2046 for ( int i = 0; i < count; i++ ) { buf[i] = p[i].ch; }
2047
2048 gc.TextOutF( x, y, buf, count );
2049 n -= count;
2050 p += count;
2051 x += count * charW;
2052 c += count;
2053 }
2054 }
2055 }
2056
2057 DrawCursor( gc );
2058 }
2059
GetCursorRect(int x,int y) const2060 crect EditWin::GetCursorRect( int x, int y ) const
2061 {
2062 return crect( x, y + charH - charH / 5, x + charW, y + charH );
2063 }
2064
SetPath(clPtr<FS> fs,FSPath & p)2065 void EditWin::SetPath( clPtr<FS> fs, FSPath& p )
2066 {
2067 _fs = fs;
2068 _path = p;
2069 }
2070
GetCharsetId()2071 int EditWin::GetCharsetId()
2072 {
2073 return charset->id;
2074 }
2075
NextCharset()2076 void EditWin::NextCharset()
2077 {
2078 SetCharset( charset_table[GetNextOperCharsetId( charset->id )] );
2079 }
2080
SetCharset(int n)2081 void EditWin::SetCharset( int n )
2082 {
2083 SetCharset( charset_table[n] );
2084 }
2085
EventKey(cevent_key * pEvent)2086 bool EditWin::EventKey( cevent_key* pEvent )
2087 {
2088 if ( pEvent->Type() == EV_KEYDOWN )
2089 {
2090 bool shift = ( pEvent->Mod() & KM_SHIFT ) != 0;
2091 bool ctrl = ( pEvent->Mod() & KM_CTRL ) != 0;
2092 bool alt = ( pEvent->Mod() & KM_ALT ) != 0;
2093
2094 if ( ctrl )
2095 {
2096 switch ( pEvent->Key() )
2097 {
2098 case VK_UP:
2099 if (pEvent->IsFromMouseWheel())
2100 {
2101 if ( g_MainWin ) g_MainWin->IncreaseFontSize(NCWin::EDIT);
2102 return true;
2103 }
2104 break;
2105
2106 case VK_DOWN:
2107 if (pEvent->IsFromMouseWheel())
2108 {
2109 if ( g_MainWin ) g_MainWin->DecreaseFontSize(NCWin::EDIT);
2110 return true;
2111 }
2112 break;
2113
2114 case VK_0:
2115 case VK_1:
2116 case VK_2:
2117 case VK_3:
2118 case VK_4:
2119 case VK_5:
2120 case VK_6:
2121 case VK_7:
2122 case VK_8:
2123 case VK_9:
2124 {
2125 int Slot = pEvent->Key() - VK_0;
2126 bool LeftCtrl = ( pEvent->ExtMod() & EXT_KM_LCTRL ) != 0;
2127 if ( LeftCtrl )
2128 {
2129 // go to bookmark
2130 sEditorScrollCtx Ctx;
2131 if ( m_ScrollCtxStorage.Get( Slot, &Ctx ) )
2132 {
2133 this->SetScrollCtx( Ctx );
2134 }
2135 }
2136 else
2137 {
2138 // set bookmark
2139 sEditorScrollCtx Ctx = this->GetScrollCtx();
2140 m_ScrollCtxStorage.Put(Slot, &Ctx);
2141 }
2142 return true;
2143 }
2144
2145 case VK_Y:
2146 DeleteLine();
2147 return true;
2148
2149 case VK_X:
2150 Cut();
2151 return true;
2152
2153 case VK_C:
2154 ToClipboard();
2155 return true;
2156
2157 case VK_V:
2158 DelMarked();
2159 FromClipboard();
2160 return true;
2161
2162 case VK_Z:
2163 if ( shift ) { Redo(); }
2164 else { Undo(); }
2165
2166 return true;
2167 }
2168 }
2169
2170
2171 switch ( pEvent->Key() )
2172 {
2173 case VK_RIGHT:
2174 if ( ctrl )
2175 {
2176 CursorCtrlRight( shift );
2177 }
2178 else
2179 {
2180 CursorRight( shift );
2181 }
2182
2183 break;
2184
2185 case VK_LEFT:
2186 if ( ctrl )
2187 {
2188 CursorCtrlLeft( shift );
2189 }
2190 else
2191 {
2192 CursorLeft( shift );
2193 }
2194
2195 break;
2196
2197 case VK_DOWN:
2198 #if defined( __APPLE__)
2199 if ( ctrl ) { PageDown( shift ); }
2200 else
2201 #endif
2202 CursorDown( shift );
2203
2204 break;
2205
2206 case VK_UP:
2207 #if defined( __APPLE__)
2208 if ( ctrl ) { PageUp( shift ); }
2209 else
2210 #endif
2211 CursorUp( shift );
2212
2213 break;
2214
2215 case VK_HOME:
2216 if ( ctrl ) { CtrlPageUp( shift ); }
2217 else { CursorHome( shift ); }
2218
2219 break;
2220
2221 case VK_END:
2222 if ( ctrl ) { CtrlPageDown( shift ); }
2223 else { CursorEnd( shift ); }
2224
2225 break;
2226
2227 case VK_NEXT:
2228 if ( ctrl ) { CtrlPageDown( shift ); }
2229 else { PageDown( shift ); }
2230
2231 break;
2232
2233 case VK_PRIOR:
2234 if ( ctrl ) { CtrlPageUp( shift ); }
2235 else { PageUp( shift ); }
2236
2237 break;
2238
2239 case VK_DELETE:
2240 if ( ctrl ) { Del( true ); return true; }
2241
2242 if ( shift ) { Cut(); return true; }
2243
2244 Del( false );
2245 break;
2246
2247 case VK_BACK:
2248 if ( alt )
2249 {
2250 Undo();
2251 }
2252 else
2253 {
2254 Backspace( ctrl );
2255 }
2256
2257 break;
2258
2259 case VK_NUMPAD_RETURN:
2260 case VK_RETURN:
2261 DelMarked();
2262 Enter();
2263 break;
2264
2265 case VK_INSERT:
2266 if ( shift )
2267 {
2268 DelMarked();
2269 FromClipboard();
2270 return true;
2271 }
2272
2273 if ( ctrl ) { ToClipboard(); return true; }
2274
2275 break;
2276
2277 default:
2278 if ( ctrl && pEvent->Key() == VK_A ) { SelectAll(); break; }
2279
2280 if ( pEvent->Char() == '\t' || pEvent->Char() >= ' ' )
2281 {
2282 DelMarked();
2283 InsChar( pEvent->Char() );
2284 return true;
2285 }
2286
2287 return false;
2288 };
2289
2290 return true;
2291 }
2292
2293 return false;
2294 }
2295
EventSize(cevent_size * pEvent)2296 void EditWin::EventSize( cevent_size* pEvent )
2297 {
2298 Win::EventSize( pEvent );
2299 rows = editRect.Height() / charH;
2300 cols = editRect.Width() / charW;
2301
2302 if ( rows <= 0 ) { rows = 1; }
2303
2304 if ( cols <= 0 ) { cols = 1; }
2305
2306 CalcScroll();
2307
2308 {
2309 int r = ( editRect.Height() + charH - 1 ) / charH;
2310 int c = ( editRect.Width() + charW - 1 ) / charW;
2311 screen.Alloc( r, c );
2312 __RefreshScreenData();
2313 Invalidate();
2314 }
2315 }
2316
2317
GetColFromPos(int line,int pos)2318 int EditWin::GetColFromPos( int line, int pos )
2319 {
2320 if ( line < 0 || line >= text.Count() ) { return 0; }
2321
2322 EditString& str = text.Get( line );
2323
2324 char* s = str.Get(), *end = s + str.Len();
2325
2326 bool tab = charset->IsTab( s, end );
2327 int col = 0;
2328
2329 while ( s )
2330 {
2331 if ( pos <= 0 ) { break; }
2332
2333 col += tab ? tabSize - col % tabSize : 1;
2334 char* t = charset->GetNext( s, end );
2335 tab = charset->IsTab( t, end );
2336
2337 if ( t ) { pos -= t - s; }
2338
2339 s = t;
2340 }
2341
2342 return col;
2343 }
2344
2345
GetPosFromCol(int line,int nCol)2346 int EditWin::GetPosFromCol( int line, int nCol )
2347 {
2348 if ( line < 0 || line >= text.Count() ) { return 0; }
2349
2350 EditString& str = text.Get( line );
2351
2352 char* s = str.Get(), *end = s + str.Len();
2353
2354 bool tab = charset->IsTab( s, end );
2355
2356 int pos = 0, col = 0;
2357
2358 while ( s )
2359 {
2360 int step = ( tab ? tabSize - ( col % tabSize ) : 1 );
2361
2362 if ( step > nCol - col )
2363 {
2364 break;
2365 }
2366
2367 col += step;
2368 char* t = charset->GetNext( s, end );
2369 tab = charset->IsTab( t, end );
2370
2371 if ( t )
2372 {
2373 pos += t - s;
2374 }
2375 else
2376 {
2377 pos = str.Len();
2378 }
2379
2380 s = t;
2381 }
2382
2383 return pos;
2384 }
2385
SetCursor(cpoint p,bool mark)2386 void EditWin::SetCursor( cpoint p, bool mark )
2387 {
2388 int r = ( p.y - editRect.top ) / charH;
2389 int c = ( p.x - editRect.left ) / charW;
2390 r += firstLine;
2391 c += colOffset;
2392
2393 if ( p.y < 0 ) { r--; }
2394
2395 if ( p.x < 0 ) { c--; }
2396
2397 int line = r;
2398
2399 if ( line >= text.Count() ) { line = text.Count() - 1; }
2400
2401 if ( line < 0 ) { line = 0; }
2402
2403 // EditString& str = text.Get( line );
2404 int pos = GetPosFromCol( line, c );
2405 cursor.Set( line, pos );
2406
2407 if ( !mark ) { marker = cursor; }
2408
2409 CursorToScreen();
2410 SendChanges();
2411 Refresh();
2412 }
2413
2414
EventTimer(int id)2415 void EditWin::EventTimer( int id )
2416 {
2417 if ( id == 0 )
2418 {
2419 wal::GC gc( this );
2420 DrawCursor( gc );
2421 return;
2422 }
2423
2424 SetCursor( lastMousePoint, true );
2425 }
2426
2427
EventMouse(cevent_mouse * pEvent)2428 bool EditWin::EventMouse( cevent_mouse* pEvent )
2429 {
2430 lastMousePoint = pEvent->Point();
2431
2432 switch ( pEvent->Type() )
2433 {
2434 case EV_MOUSE_MOVE:
2435 if ( IsCaptured() )
2436 {
2437 SetCursor( lastMousePoint, true );
2438 }
2439
2440 break;
2441
2442 case EV_MOUSE_PRESS:
2443 {
2444 if ( pEvent->Button() == MB_X1 )
2445 {
2446 PageUp( false );
2447 break;
2448 }
2449
2450 if ( pEvent->Button() == MB_X2 )
2451 {
2452 PageDown( false );
2453 break;
2454 }
2455
2456 if ( pEvent->Button() != MB_L )
2457 {
2458 break;
2459 }
2460
2461 SetCapture();
2462 SetCursor( lastMousePoint, false );
2463
2464 SetTimer( 1, 100 );
2465 }
2466 break;
2467
2468
2469 case EV_MOUSE_RELEASE:
2470 if ( pEvent->Button() != MB_L )
2471 {
2472 break;
2473 }
2474
2475 DelTimer( 1 );
2476
2477 ReleaseCapture();
2478 break;
2479 };
2480
2481 return false;
2482 }
2483
Search(const unicode_t * arg,bool sens)2484 bool EditWin::Search( const unicode_t* arg, bool sens )
2485 {
2486 std::vector<unicode_t> search = new_unicode_str( arg );
2487
2488 if ( !sens )
2489 for ( unicode_t* u = search.data(); *u; u++ ) { *u = UnicodeLC( *u ); }
2490
2491 int line = cursor.line;
2492
2493 EditString& str = text.Get( line );
2494 char* begin = str.Get(), *end = begin + str.Len();
2495 char* s = begin + cursor.pos;
2496
2497 //bool tab;
2498 if ( s < end )
2499 {
2500 s = charset->GetNext( s, end );
2501 }
2502
2503 while ( true )
2504 {
2505 while ( s )
2506 {
2507 const unicode_t* sPtr = search.data();
2508
2509 for ( char* p = s; ; p = charset->GetNext( p, end ), sPtr++ )
2510 {
2511 if ( !*sPtr )
2512 {
2513 cursor.Set( line, s - begin );
2514 marker = cursor;
2515 CursorToScreen();
2516 SendChanges();
2517 Refresh();
2518 return true;
2519 }
2520
2521 if ( !p ) { break; }
2522
2523 unicode_t c = charset->GetChar( p, end );
2524
2525 if ( sens )
2526 {
2527 if ( c != *sPtr ) { break; }
2528 }
2529 else
2530 {
2531 if ( UnicodeLC( c ) != *sPtr ) { break; }
2532 }
2533 }
2534
2535 s = charset->GetNext( s, end );
2536 }
2537
2538 line++;
2539
2540 if ( line >= text.Count() ) { break; }
2541
2542 EditString& str = text.Get( line );
2543 s = begin = str.Get();
2544 end = begin + str.Len();
2545 }
2546
2547 return false;
2548 }
2549
2550 #define CMD_REPLACE 1000
2551 #define CMD_ALL 1001
2552 #define CMD_SKIP 1002
2553
2554 static ButtonDataNode bReplaceAllSkipCancel[] = { {"&Replace", CMD_REPLACE}, { "&All", CMD_ALL}, { "&Skip", CMD_SKIP}, {"&Cancel", CMD_CANCEL}, {0, 0}};
2555
Replace(const unicode_t * from,const unicode_t * to,bool sens)2556 bool EditWin::Replace( const unicode_t* from, const unicode_t* to, bool sens )
2557 {
2558 std::vector<unicode_t> search = new_unicode_str( from );
2559
2560 if ( !sens )
2561 for ( unicode_t* u = search.data(); *u; u++ ) { *u = UnicodeLC( *u ); }
2562
2563 ccollect<char> rep;
2564 charset_struct* cs = charset;
2565
2566 for ( ; *to; to++ )
2567 {
2568 char buf[32];
2569 int n = cs->SetChar( buf, *to );
2570
2571 for ( int i = 0; i < n; i++ )
2572 {
2573 rep.append( buf[i] );
2574 }
2575 }
2576
2577 int line = cursor.line;
2578
2579 EditString& str = text.Get( line );
2580 char* begin = str.Get(), *end = begin + str.Len();
2581 char* s = begin + cursor.pos;
2582
2583 if ( s < end )
2584 {
2585 s = charset->GetNext( s, end );
2586 }
2587
2588 bool all = false;
2589 int foundCount = 0;
2590
2591 clPtr<UndoBlock> undoBlock = new UndoBlock( false, _changed );
2592 undoBlock->SetBeginPos( cursor, marker );
2593
2594 try
2595 {
2596 while ( true )
2597 {
2598 while ( s )
2599 {
2600
2601 restart:
2602
2603 const unicode_t* sPtr = search.data();
2604
2605 for ( char* p = s; ; p = charset->GetNext( p, end ), sPtr++ )
2606 {
2607 if ( !*sPtr )
2608 {
2609 char* blockEnd = ( p ? p : end );
2610
2611 foundCount++;
2612
2613 if ( !all )
2614 {
2615 marker.Set( line, s - begin );
2616 cursor.Set( line, blockEnd - begin );
2617 CursorToScreen_forReplace();
2618 SendChanges();
2619 Refresh();
2620
2621 int ret = NCMessageBox( ( NCDialogParent* )Parent(), _LT( "Replace" ), _LT( "Replace it?" ), false, bReplaceAllSkipCancel );
2622
2623 if ( ret == CMD_ALL ) { all = true; }
2624
2625 if ( ret == CMD_SKIP ) { continue; }
2626
2627 if ( ret != CMD_ALL && ret != CMD_REPLACE )
2628 {
2629 marker = cursor;
2630
2631 //!!
2632 undoBlock->SetEndPos( cursor, marker );
2633 undoList.Append( undoBlock );
2634
2635 CursorToScreen();
2636 SendChanges();
2637 Refresh();
2638 return true;
2639 }
2640 }
2641
2642 {
2643 //replace
2644 int pos = s - begin;
2645 int size = blockEnd - s;
2646 SetChanged( line );
2647
2648 EditString& str = text.Get( line );
2649
2650 undoBlock->DelText( line, pos, str.Get() + pos, size );
2651 str.Delete( pos, size );
2652
2653 if ( rep.count() > 0 )
2654 {
2655 str.Insert( rep.ptr(), pos, rep.count() );
2656 undoBlock->InsText( line, pos, rep.ptr(), rep.count() );
2657 }
2658
2659 begin = str.Get();
2660 end = begin + str.Len();
2661 s = begin + pos + rep.count();
2662
2663 cursor.Set( line, s - begin );
2664 marker = cursor;
2665
2666 if ( !p ) { break; }
2667
2668 goto restart;
2669 }
2670 }
2671
2672 if ( !p ) { break; }
2673
2674 unicode_t c = charset->GetChar( p, end );
2675
2676 if ( sens )
2677 {
2678 if ( c != *sPtr ) { break; }
2679 }
2680 else
2681 {
2682 if ( UnicodeLC( c ) != *sPtr ) { break; }
2683 }
2684 }
2685
2686 s = charset->GetNext( s, end );
2687 }
2688
2689 line++;
2690
2691 if ( line >= text.Count() ) { break; }
2692
2693 EditString& str = text.Get( line );
2694 s = begin = str.Get();
2695 end = begin + str.Len();
2696 }
2697
2698 marker = cursor;
2699
2700 undoBlock->SetEndPos( cursor, marker );
2701 undoList.Append( undoBlock );
2702
2703 CursorToScreen();
2704 SendChanges();
2705 Refresh();
2706
2707 }
2708 catch ( ... )
2709 {
2710 undoList.Clear();
2711 throw;
2712 }
2713
2714 return foundCount > 0;
2715 }
2716
2717
~EditWin()2718 EditWin::~EditWin()
2719 {
2720 DelTimer( 0 );
2721 }
2722
2723
2724