Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGText.cxx
Go to the documentation of this file.
1// @(#)root/gui:$Id: ba5caabd5d69c640536a71daaa6968de966be4a8 $
2// Author: Fons Rademakers 26/04/98
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11/**************************************************************************
12
13 This source is based on Xclass95, a Win95-looking GUI toolkit.
14 Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
15
16 Xclass95 is free software; you can redistribute it and/or
17 modify it under the terms of the GNU Library General Public
18 License as published by the Free Software Foundation; either
19 version 2 of the License, or (at your option) any later version.
20
21**************************************************************************/
22
23
24/** \class TGText
25 \ingroup guiwidgets
26
27A TGText is a multi line text buffer. It allows the text to be
28loaded from file, saved to file and edited. It is used in the
29TGTextEdit widget. Single line text is handled by TGTextBuffer
30and the TGTextEntry widget.
31
32*/
33
34
35#include "TGText.h"
36#include "strlcpy.h"
37#include <cctype>
38
39const Int_t kMaxLen = 8000;
40
41
42
43////////////////////////////////////////////////////////////////////////////////
44/// Create empty line of text (default ctor).
45
47{
48 fLength = 0;
49 fString = 0;
50 fPrev = fNext = 0;
51}
52
53////////////////////////////////////////////////////////////////////////////////
54/// Initialize line of text with other line of text (not copy ctor).
55
57{
58 fLength = line->GetLineLength();
59 fString = 0;
60 if (fLength > 0)
61 fString = line->GetText(0, line->GetLineLength());
62 fPrev = fNext = 0;
63}
64
65////////////////////////////////////////////////////////////////////////////////
66/// Initialize line of text with a const char*.
67
68TGTextLine::TGTextLine(const char *string)
69{
70 if (string) {
71 fLength = strlen(string);
72 fString = new char[fLength+1];
73 strlcpy(fString, string, fLength+1);
74 } else {
75 fLength = 0;
76 fString = 0;
77 }
78 fPrev = fNext = 0;
79}
80
81////////////////////////////////////////////////////////////////////////////////
82///copy constructor
83
84TGTextLine::TGTextLine(const TGTextLine& tl) : fLength(tl.fLength),
85 fPrev(tl.fPrev), fNext(tl.fNext)
86{
87 fString = 0;
88 if (tl.fString) {
89 fString = new char[fLength+1];
90 strncpy(fString, tl.fString, fLength);
91 fString[fLength] = 0;
92 }
93}
94
95////////////////////////////////////////////////////////////////////////////////
96///assignment operator
97
99{
100 if (this != &tl) {
101 fLength = tl.fLength;
102 if (fString) delete [] fString;
103 fString = new char[fLength+1];
104 strncpy(fString, tl.fString, fLength);
105 fString[fLength] = 0;
106 fPrev = tl.fPrev;
107 fNext = tl.fNext;
108 }
109 return *this;
110}
111
112////////////////////////////////////////////////////////////////////////////////
113/// Delete a line of text.
114
116{
117 if (fString)
118 delete [] fString;
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// Clear a line of text.
123
125{
126 if (fString)
127 delete [] fString;
128 fString = 0;
129 fLength = 0;
130}
131
132////////////////////////////////////////////////////////////////////////////////
133/// Delete length chars from line starting at position pos.
134
136{
137 if (fLength == 0 || pos >= fLength)
138 return;
139 if (pos+length > fLength)
140 length = fLength - pos;
141
142 if (fLength - length <= 0) {
143 delete [] fString;
144 fLength = 0;
145 fString = 0;
146 return;
147 }
148 char *newstring = new char[fLength - length+1];
151 delete [] fString;
154 fString[fLength] = '\0';
155}
156
157////////////////////////////////////////////////////////////////////////////////
158/// Insert text in line starting at position pos.
159
160void TGTextLine::InsText(ULong_t pos, const char *text)
161{
162 if (pos > fLength || !text)
163 return;
164
165 char *newstring = new char[strlen(text)+fLength+1];
166 if (fString != 0)
168 // coverity[secure_coding]
169 strcpy(newstring+pos, text);
170 if (fString != 0 && fLength - pos > 0)
173 delete [] fString;
175 fString[fLength] ='\0';
176}
177
178////////////////////////////////////////////////////////////////////////////////
179/// Get length characters from line starting at pos. Returns 0
180/// in case pos and length are out of range. The returned string
181/// must be freed by the user.
182
184{
185 if (pos >= fLength) {
186 return 0;
187 }
188
189 if (pos + length > fLength) {
190 length = fLength - pos;
191 }
192
193 char *retstring = new char[length+1];
194 retstring[length] = '\0';
196
197 return retstring;
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Get word at position. Returned string must be deleted.
202
204{
205 if (pos >= fLength) {
206 return 0;
207 }
208
209 Int_t start = (Int_t)pos;
210 UInt_t end = (UInt_t)pos;
211 UInt_t i = (UInt_t)pos;
212
213 if (fString[i] == ' ' || fString[i] == '\t') {
214 while (start >= 0) {
215 if (fString[start] == ' ' || fString[start] == '\t') --start;
216 else break;
217 }
218 ++start;
219 while (end < fLength) {
220 if (fString[end] == ' ' || fString[end] == '\t') ++end;
221 else break;
222 }
223 } else if (isalnum(fString[i])) {
224 while (start >= 0) {
225 if (isalnum(fString[start])) --start;
226 else break;
227 }
228 ++start;
229 while (end < fLength) {
230 if (isalnum(fString[end])) ++end;
231 else break;
232 }
233 } else {
234 while (start >= 0) {
235 if (isalnum(fString[start]) || fString[start] == ' ' || fString[start] == '\t') {
236 break;
237 } else {
238 --start;
239 }
240 }
241 ++start;
242 while (end < fLength) {
243 if (isalnum(fString[end]) || fString[end] == ' ' || fString[end] == '\t') {
244 break;
245 } else {
246 ++end;
247 }
248 }
249 }
250
251 UInt_t length = UInt_t(end - start);
252 char *retstring = new char[length+1];
253 retstring[length] = '\0';
255
256 return retstring;
257}
258
259////////////////////////////////////////////////////////////////////////////////
260/// Delete a character from the line.
261
263{
264 char *newstring;
265 if ((fLength <= 0) || (pos > fLength))
266 return;
267 newstring = new char[fLength];
269 if (pos < fLength)
270 strncpy(newstring+pos-1, fString+pos, UInt_t(fLength-pos+1));
271 else
272 newstring[pos-1] = 0;
273 delete [] fString;
275 fLength--;
276}
277
278////////////////////////////////////////////////////////////////////////////////
279/// Insert a character at the specified position.
280
282{
283 char *newstring;
284 if (pos > fLength)
285 return;
286 newstring = new char[fLength+2];
287 newstring[fLength+1] = '\0';
288 if (fLength > 0)
290 newstring[pos] = character;
291 if (fLength - pos > 0)
292 strncpy(newstring+pos+1, fString+pos, UInt_t(fLength-pos));
293 delete [] fString;
295 fLength++;
296}
297
298////////////////////////////////////////////////////////////////////////////////
299/// Get a character at the specified position from the line.
300/// Returns -1 if pos is out of range.
301
303{
304 if ((fLength <= 0) || (pos >= fLength))
305 return -1;
306 return fString[pos];
307}
308
309
310
311////////////////////////////////////////////////////////////////////////////////
312///copy constructor
313
315 fFilename(gt.fFilename),
316 fIsSaved(gt.fIsSaved),
318 fCurrent(gt.fCurrent),
319 fCurrentRow(gt.fCurrentRow),
320 fRowCount(gt.fRowCount),
321 fColCount(gt.fColCount),
322 fLongestLine(gt.fLongestLine)
323{
324}
325
326////////////////////////////////////////////////////////////////////////////////
327///assignment operator
328
330{
331 if(this!=&gt) {
332 fFilename=gt.fFilename;
333 fIsSaved=gt.fIsSaved;
334 fFirst=gt.fFirst;
335 fCurrent=gt.fCurrent;
336 fCurrentRow=gt.fCurrentRow;
337 fRowCount=gt.fRowCount;
338 fColCount=gt.fColCount;
339 fLongestLine=gt.fLongestLine;
340 }
341 return *this;
342}
343
344////////////////////////////////////////////////////////////////////////////////
345/// Common initialization method.
346
348{
349 fFirst = new TGTextLine;
351 fCurrentRow = 0;
352 fColCount = 0;
353 fRowCount = 1;
354 fLongestLine = 0;
355 fIsSaved = kTRUE;
356}
357
358////////////////////////////////////////////////////////////////////////////////
359/// Create default (empty) text buffer.
360
362{
363 Init();
364}
365
366////////////////////////////////////////////////////////////////////////////////
367/// Create text buffer and initialize with other text buffer.
368
370{
371 TGLongPosition pos, end;
372
373 pos.fX = pos.fY = 0;
374 end.fY = text->RowCount() - 1;
375 end.fX = text->GetLineLength(end.fY) - 1;
376 Init();
377 InsText(pos, text, pos, end);
378}
379
380////////////////////////////////////////////////////////////////////////////////
381/// Create text buffer and initialize with single line string.
382
383TGText::TGText(const char *string)
384{
385 TGLongPosition pos;
386
387 pos.fX = pos.fY = 0;
388 Init();
389 InsText(pos, string);
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// Destroy text buffer.
394
396{
397 Clear();
398 delete fFirst;
399}
400
401////////////////////////////////////////////////////////////////////////////////
402/// Clear text buffer.
403
405{
408 while (travel != 0) {
410 travel = travel->fNext;
411 delete toDelete;
412 }
413 fFirst->Clear();
414 fFirst->fNext = 0;
416 fCurrentRow = 0;
417 fColCount = 0;
418 fRowCount = 1;
419 fLongestLine = 0;
420 fIsSaved = kTRUE;
421 fFilename = "";
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Load text from file fn. Startpos is the begin from where to
426/// load the file and length is the number of characters to read
427/// from the file.
428
430{
431 Bool_t isFirst = kTRUE;
432 Bool_t finished = kFALSE;
433 Long_t count, charcount, i, cnt;
434 FILE *fp;
435 char *buf, c, *src, *dst, *buffer, *buf2;
436 TGTextLine *travel, *temp;
437
438 travel = fFirst;
439
440 if (!(fp = fopen(fn, "r"))) return kFALSE;
441 buf = new char[kMaxLen];
442 i = 0;
443 fseek(fp, startpos, SEEK_SET);
444 charcount = 0;
445 while (fgets(buf, kMaxLen, fp)) {
446 if ((length != -1) && (charcount+(Int_t)strlen(buf) > length)) {
447 count = length - charcount;
448 finished = kTRUE;
449 } else
450 count = kMaxLen;
451 charcount += strlen(buf);
452 buf2 = new char[count+1];
453 buf2[count] = '\0';
454 src = buf;
455 dst = buf2;
456 cnt = 0;
457 while ((c = *src++)) {
458 // Don't put CR or NL in buffer
459 if (c == 0x0D || c == 0x0A)
460 break;
461 // Expand tabs
462 else if (c == 0x09) {
463 *dst++ = '\t';
464 while (((dst-buf2) & 0x7) && (cnt++ < count-1))
465 *dst++ = 16; //*dst++ = ' ';
466 } else
467 *dst++ = c;
468 if (cnt++ >= count-1) break;
469 }
470 *dst = '\0';
471 temp = new TGTextLine;
472 const size_t bufferSize = strlen(buf2)+1;
473 buffer = new char[bufferSize];
474 strlcpy(buffer, buf2, bufferSize);
475 temp->fLength = strlen(buf2);
476 temp->fString = buffer;
477 temp->fNext = temp->fPrev = 0;
478 if (isFirst) {
479 delete fFirst;
480 fFirst = temp;
481 fCurrent = temp;
482 travel = fFirst;
483 isFirst = kFALSE;
484 } else {
485 travel->fNext = temp;
486 temp->fPrev = travel;
487 travel = travel->fNext;
488 }
489 ++i;
490 delete [] buf2;
491 if (finished)
492 break;
493 }
494 fclose(fp);
495 delete [] buf;
496
497 // Remember the number of lines
498 fRowCount = i;
499 if (fRowCount == 0)
500 fRowCount++;
501 fIsSaved = kTRUE;
502 fFilename = fn;
503 LongestLine();
504
505 return kTRUE;
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// Load a 0 terminated buffer. Lines will be split at '\n'.
510
512{
513 Bool_t isFirst = kTRUE;
514 Bool_t finished = kFALSE, lastnl = kFALSE;
515 Long_t i, cnt;
516 TGTextLine *travel, *temp;
517 char *buf, c, *src, *dst, *buffer, *buf2, *s;
518 const char *tbuf = txtbuf;
519
520 travel = fFirst;
521
522 if (!tbuf || !tbuf[0])
523 return kFALSE;
524
525 buf = new char[kMaxLen];
526 i = 0;
527next:
528 if ((s = (char*)strchr(tbuf, '\n'))) {
529 if (s-tbuf+1 >= kMaxLen-1) {
530 strncpy(buf, tbuf, kMaxLen-2);
531 buf[kMaxLen-2] = '\n';
532 buf[kMaxLen-1] = 0;
533 } else {
534 strncpy(buf, tbuf, s-tbuf+1);
535 buf[s-tbuf+1] = 0;
536 }
537 tbuf = s+1;
538 } else {
539 strncpy(buf, tbuf, kMaxLen-1);
540 buf[kMaxLen-1] = 0;
541 finished = kTRUE;
542 }
543
544 buf2 = new char[kMaxLen+1];
545 buf2[kMaxLen] = '\0';
546 src = buf;
547 dst = buf2;
548 cnt = 0;
549 while ((c = *src++)) {
550 // Don't put CR or NL in buffer
551 if (c == 0x0D || c == 0x0A)
552 break;
553 // Expand tabs
554 else if (c == 0x09) {
555 *dst++ = '\t';
556 while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1))
557 *dst++ = 16; //*dst++ = ' ';
558 } else
559 *dst++ = c;
560 if (cnt++ >= kMaxLen-1) break;
561 }
562 *dst = '\0';
563 temp = new TGTextLine;
564 const size_t bufferSize = strlen(buf2) + 1;
565 buffer = new char[bufferSize];
566 strlcpy(buffer, buf2, bufferSize);
567 temp->fLength = strlen(buf2);
568 temp->fString = buffer;
569 temp->fNext = temp->fPrev = 0;
570 if (isFirst) {
571 delete fFirst;
572 fFirst = temp;
573 fCurrent = temp;
574 travel = fFirst;
575 isFirst = kFALSE;
576 } else {
577 travel->fNext = temp;
578 temp->fPrev = travel;
579 travel = travel->fNext;
580 }
581 ++i;
582 delete [] buf2;
583
584 // make sure that \n generates a single empty line in the TGText
585 if (!lastnl && !*tbuf && *(tbuf-1) == '\n') {
586 tbuf--;
587 lastnl = kTRUE;
588 }
589
590 if (!finished && strlen(tbuf))
591 goto next;
592
593 delete [] buf;
594 // Remember the number of lines
595 fRowCount = i;
596 if (fRowCount == 0)
597 fRowCount++;
598 fIsSaved = kTRUE;
599 fFilename = "";
600 LongestLine();
601
602 return kTRUE;
603}
604
605////////////////////////////////////////////////////////////////////////////////
606/// Save text buffer to file fn.
607
609{
610 char *buffer;
612 FILE *fp;
613 if (!(fp = fopen(fn, "w"))) return kFALSE;
614
615 while (travel) {
616 ULong_t i = 0;
617 buffer = new char[travel->fLength+2];
618 strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
619 buffer[travel->fLength] = '\n';
620 buffer[travel->fLength+1] = '\0';
621 while (buffer[i] != '\0') {
622 if (buffer[i] == '\t') {
623 ULong_t j = i+1;
624 while (buffer[j] == 16)
625 j++;
626 // coverity[secure_coding]
627 strcpy(buffer+i+1, buffer+j);
628 }
629 i++;
630 }
631 if (fputs(buffer, fp) == EOF) {
632 delete [] buffer;
633 fclose(fp);
634 return kFALSE;
635 }
636 delete [] buffer;
637 travel = travel->fNext;
638 }
639 fIsSaved = kTRUE;
640 fFilename = fn;
641 fclose(fp);
642
643 return kTRUE;
644}
645
646////////////////////////////////////////////////////////////////////////////////
647/// Append buffer to file fn.
648
650{
651 char *buffer;
653 FILE *fp;
654 if (!(fp = fopen(fn, "a"))) return kFALSE;
655
656 while (travel) {
657 ULong_t i = 0;
658 buffer = new char[travel->fLength+2];
659 strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
660 buffer[travel->fLength] = '\n';
661 buffer[travel->fLength+1] = '\0';
662 while (buffer[i] != '\0') {
663 if (buffer[i] == '\t') {
664 ULong_t j = i+1;
665 while (buffer[j] == 16 && buffer[j] != '\0')
666 j++;
667 // coverity[secure_coding]
668 strcpy(buffer+i+1, buffer+j);
669 }
670 i++;
671 }
672 if (fputs(buffer, fp) == EOF) {
673 delete [] buffer;
674 fclose(fp);
675 return kFALSE;
676 }
677 delete [] buffer;
678 travel = travel->fNext;
679 }
680 fIsSaved = kTRUE;
681 fclose(fp);
682
683 return kTRUE;
684}
685
686////////////////////////////////////////////////////////////////////////////////
687/// Delete character at specified position pos.
688
690{
691 if ((pos.fY >= fRowCount) || (pos.fY < 0))
692 return kFALSE;
693
694 if (!SetCurrentRow(pos.fY)) return kFALSE;
695 fCurrent->DelChar(pos.fX);
696
698 LongestLine();
699 return kTRUE;
700}
701
702////////////////////////////////////////////////////////////////////////////////
703/// Insert character c at the specified position pos.
704
706{
707 if ((pos.fY >= fRowCount) || (pos.fY < 0) || (pos.fX < 0))
708 return kFALSE;
709
710 if (!SetCurrentRow(pos.fY)) return kFALSE;
711 fCurrent->InsChar(pos.fX, c);
712
714 LongestLine();
715 return kTRUE;
716}
717
718////////////////////////////////////////////////////////////////////////////////
719/// Get character a position pos. If character not valid return -1.
720
722{
723 if (pos.fY >= fRowCount)
724 return -1;
725
726 if (!SetCurrentRow(pos.fY)) return -1;
727 return fCurrent->GetChar(pos.fX);
728}
729
730////////////////////////////////////////////////////////////////////////////////
731/// Delete text between start and end positions. Returns false in
732/// case of failure (start and end not being within bounds).
733
735{
736 if ((start.fY < 0) || (start.fY >= fRowCount) ||
737 (end.fY < 0) || (end.fY >= fRowCount)) {
738 return kFALSE;
739 }
740
741 if ((end.fX < 0) || (end.fX > GetLineLength(end.fY))) {
742 return kFALSE;
743 }
744
745 char *tempbuffer;
746
747 if (!SetCurrentRow(start.fY)) return kFALSE;
748
749 if (start.fY == end.fY) {
750 fCurrent->DelText(start.fX, end.fX-start.fX+1);
751 return kTRUE;
752 }
753 fCurrent->DelText(start.fX, fCurrent->fLength-start.fX);
755 for (Long_t i = start.fY+1; i < end.fY; i++) {
757 }
758
759 tempbuffer = fCurrent->GetText(end.fX+1, fCurrent->fLength-end.fX-1);
761 SetCurrentRow(start.fY);
762 if (tempbuffer) {
764 delete [] tempbuffer;
765 } else {
766 if (fCurrent->fNext) {
769 SetCurrentRow(start.fY);
770 }
771 }
772
774 LongestLine();
775 return kTRUE;
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Insert src text from start_src to end_src into text at position ins_pos.
780/// Returns false in case of failure (start_src, end_src out of range for
781/// src, and ins_pos out of range for this).
782
785{
786 /*
787 if ((start_src.fY < 0) || (start_src.fY >= src->RowCount()) ||
788 (end_src.fY < 0) || (end_src.fY >= src->RowCount()))
789 return kFALSE;
790 if ((start_src.fX < 0) || (start_src.fX > src->GetLineLength(start_src.fY)) ||
791 (end_src.fX < 0) || (end_src.fX > src->GetLineLength(end_src.fY)))
792 return kFALSE;
793 if ((ins_pos.fY < 0) || (ins_pos.fY > fRowCount))
794 return kFALSE;
795 if ((ins_pos.fX < 0) || (ins_pos.fX > GetLineLength(ins_pos.fY)))
796 return kFALSE;
797 */
798 if (ins_pos.fY > fRowCount)
799 return kFALSE;
800
801 TGLongPosition pos;
802 ULong_t len;
803 char *lineString;
804 char *restString;
806
807 if (ins_pos.fY == fRowCount) { // for appending text
808 pos.fY = fRowCount - 1;
809 pos.fX = GetLineLength(pos.fY);
810 BreakLine(pos); // current row is set by this
811 } else {
812 // otherwise going to the desired row
813 if (!SetCurrentRow(ins_pos.fY)) return kFALSE;
814 }
815
816 // preparing first line to be inserted
820 // inserting first line
821 if (start_src.fY == end_src.fY) {
822 len = end_src.fX - start_src.fX+1;
823 } else {
824 len = src->GetLineLength(start_src.fY) - start_src.fX;
825 }
826
827 if (len > 0) {
828 lineString = src->GetLine(start_src, len);
830 delete [] lineString;
831 }
832 // [...] inserting possible lines
833 pos.fY = start_src.fY+1;
834 pos.fX = 0;
835 for ( ; pos.fY < end_src.fY; pos.fY++) {
836 Int_t llen = src->GetLineLength(pos.fY);
837 lineString = src->GetLine(pos, llen > 0 ? llen : 0);
841 fRowCount++;
842 fCurrentRow++;
843 delete [] lineString;
844 }
845 // last line of inserted text is as special as first line
846 if (start_src.fY != end_src.fY) {
847 pos.fY = end_src.fY;
848 pos.fX = 0;
849 lineString = src->GetLine(pos, end_src.fX+1);
853 fRowCount++;
854 fCurrentRow++;
855 delete [] lineString;
856 }
857 // ok, now we have to add the rest of the first destination line
858 if (restString) {
859#if 0
860 if (ins_pos.fX == 0) {
864 fRowCount++;
865 fCurrentRow++;
866 } else
867#endif
869 delete [] restString;
870 }
871 // now re-linking the rest of the origin text
873 if (fCurrent->fNext) {
875 }
876
877 LongestLine();
879 return kTRUE;
880}
881
882////////////////////////////////////////////////////////////////////////////////
883/// Insert single line at specified position. Return false in case position
884/// is out of bounds.
885
886Bool_t TGText::InsText(TGLongPosition pos, const char *buffer)
887{
888 if (pos.fY < 0 || pos.fY > fRowCount) {
889 return kFALSE;
890 }
891
892 if (pos.fY == fRowCount) {
894 fCurrent->fNext = new TGTextLine(buffer);
896 fRowCount++;
897 } else {
898 SetCurrentRow(pos.fY);
899 fCurrent->InsText(pos.fX, buffer);
900 }
901 LongestLine();
903 return kTRUE;
904}
905
906////////////////////////////////////////////////////////////////////////////////
907/// Add another text buffer to this buffer.
908
910{
912
913 end.fY = fRowCount;
914 end.fX = 0;
915 start_src.fX = start_src.fY = 0;
916 end_src.fY = text->RowCount()-1;
917 end_src.fX = text->GetLineLength(end_src.fY)-1;
919 return InsText(end, text, start_src, end_src);
920}
921
922////////////////////////////////////////////////////////////////////////////////
923/// Insert string before specified position.
924/// Returns false if insertion failed.
925
926Bool_t TGText::InsLine(ULong_t pos, const char *string)
927{
929 if ((Long_t)pos > fRowCount) {
930 return kFALSE;
931 }
932 if ((Long_t)pos < fRowCount) {
933 SetCurrentRow(pos);
934 } else {
936 }
937
938 if (!fCurrent) return kFALSE;
939
941 newline = new TGTextLine(string);
942 newline->fPrev = previous;
943 if (previous) {
944 previous->fNext = newline;
945 } else {
946 fFirst = newline;
947 }
948
949 newline->fNext = fCurrent;
951 fRowCount++;
952 fCurrentRow++;
953
954 LongestLine();
956 return kTRUE;
957}
958
959////////////////////////////////////////////////////////////////////////////////
960/// Delete specified row. Returns false if row does not exist.
961
963{
964 if (!SetCurrentRow(pos) || (fRowCount == 1)) {
965 return kFALSE;
966 }
967
969 if (travel == fFirst) {
971 fFirst->fPrev = 0;
972 } else {
973 travel->fPrev->fNext = travel->fNext;
974 if (travel->fNext) {
975 travel->fNext->fPrev = travel->fPrev;
977 } else {
979 fCurrentRow--;
980 }
981 }
982 delete travel;
983
984 fRowCount--;
986 LongestLine();
987
988 return kTRUE;
989}
990
991////////////////////////////////////////////////////////////////////////////////
992/// Return string at position pos. Returns 0 in case pos is not valid.
993/// The returned string must be deleted by the user.
994
996{
997 if (SetCurrentRow(pos.fY)) {
998 return fCurrent->GetText(pos.fX, length);
999 }
1000 return 0;
1001}
1002
1003////////////////////////////////////////////////////////////////////////////////
1004/// Break line at position pos. Returns false if pos is not valid.
1005
1007{
1008 if (!SetCurrentRow(pos.fY))
1009 return kFALSE;
1010 if ((pos.fX < 0) || (pos.fX > (Long_t)fCurrent->fLength))
1011 return kFALSE;
1012
1013 TGTextLine *temp;
1014 char *tempbuffer;
1015 if (pos.fX < (Long_t)fCurrent->fLength) {
1017 temp = new TGTextLine(tempbuffer);
1018 fCurrent->DelText(pos.fX, fCurrent->fLength - pos.fX);
1019 delete [] tempbuffer;
1020 } else {
1021 temp = new TGTextLine;
1022 }
1023 temp->fPrev = fCurrent;
1024 temp->fNext = fCurrent->fNext;
1025 fCurrent->fNext = temp;
1026 if (temp->fNext) {
1027 temp->fNext->fPrev = temp;
1028 }
1029
1030 fIsSaved = kFALSE;
1031 fRowCount++;
1032 fCurrentRow++;
1034 LongestLine();
1035 return kTRUE;
1036}
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Get length of specified line. Returns -1 if row does not exist.
1040
1042{
1043 if (!SetCurrentRow(row)) {
1044 return -1;
1045 }
1046 return (Long_t)fCurrent->GetLineLength();
1047}
1048
1049////////////////////////////////////////////////////////////////////////////////
1050/// Make specified row the current row. Returns false if row does not exist.
1051/// In which case fCurrent is not changed or set to the last valid line.
1052
1054{
1055 Long_t count;
1056 if ((row < 0) || (row >= fRowCount)) {
1057 return kFALSE;
1058 }
1059 if (row > fCurrentRow) {
1060 for (count = fCurrentRow; count < row; count++) {
1061 if (!fCurrent->fNext) {
1062 fCurrentRow = count;
1063 return kFALSE;
1064 }
1066 }
1067 } else {
1068 if (fCurrentRow == row)
1069 return kTRUE;
1070 for (count = fCurrentRow; count > row; count--) {
1071 if (!fCurrent->fPrev) {
1072 fCurrentRow = count;
1073 return kFALSE;
1074 }
1076 }
1077 }
1078 fCurrentRow = row;
1079 return kTRUE;
1080}
1081
1082////////////////////////////////////////////////////////////////////////////////
1083/// Redo all tabs in a line. Needed after a new tab is inserted.
1084
1086{
1087 if (!SetCurrentRow(row)) {
1088 return;
1089 }
1090
1091 // first remove all special tab characters (16)
1092 char *buffer;
1093 ULong_t i = 0;
1094
1095 buffer = fCurrent->fString;
1096 while (buffer[i] != '\0') {
1097 if (buffer[i] == '\t') {
1098 ULong_t j = i+1;
1099 while (buffer[j] == 16 && buffer[j] != '\0') {
1100 j++;
1101 }
1102 // coverity[secure_coding]
1103 strcpy(buffer+i+1, buffer+j);
1104 }
1105 i++;
1106 }
1107
1108 char c, *src, *dst, *buf2;
1109 Long_t cnt;
1110
1111 buf2 = new char[kMaxLen+1];
1112 buf2[kMaxLen] = '\0';
1113 src = buffer;
1114 dst = buf2;
1115 cnt = 0;
1116 while ((c = *src++)) {
1117 // Expand tabs
1118 if (c == 0x09) {
1119 *dst++ = '\t';
1120 while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1)) {
1121 *dst++ = 16;
1122 }
1123 } else {
1124 *dst++ = c;
1125 }
1126 if (cnt++ >= kMaxLen-1) break;
1127 }
1128 *dst = '\0';
1129
1132
1133 delete [] buffer;
1134}
1135
1136////////////////////////////////////////////////////////////////////////////////
1137/// Search for string searchString starting at the specified position going
1138/// in forward (direction = true) or backward direction. Returns true if
1139/// found and foundPos is set accordingly.
1140
1142 const char *searchString,
1144{
1145 if (!SetCurrentRow(start.fY))
1146 return kFALSE;
1147
1148 Ssiz_t x = kNPOS;
1149
1150 if (direction) {
1151 while(1) {
1153 x = s.Index(searchString, (Ssiz_t)start.fX,
1155 if (x != kNPOS) {
1156 foundPos->fX = x;
1157 foundPos->fY = fCurrentRow;
1158 return kTRUE;
1159 }
1160 if (!SetCurrentRow(fCurrentRow+1))
1161 break;
1162 start.fX = 0;
1163 }
1164 } else {
1165 while(1) {
1167 for (int i = (int)start.fX; i >= 0; i--) {
1168 x = s.Index(searchString, (Ssiz_t)i,
1170 if (x >= start.fX) {
1171 x = kNPOS;
1172 continue;
1173 }
1174 if (x != kNPOS) {
1175 break;
1176 }
1177 }
1178 if (x != kNPOS) {
1179 foundPos->fX = x;
1180 foundPos->fY = fCurrentRow;
1181 return kTRUE;
1182 }
1183 if (!SetCurrentRow(fCurrentRow-1)) {
1184 break;
1185 }
1186 start.fX = fCurrent->fLength;
1187 }
1188 }
1189 return kFALSE;
1190}
1191
1192////////////////////////////////////////////////////////////////////////////////
1193/// Replace oldText by newText. Returns false if nothing replaced.
1194
1195Bool_t TGText::Replace(TGLongPosition start, const char *oldText, const char *newText,
1197{
1198 if (!SetCurrentRow(start.fY)) {
1199 return kFALSE;
1200 }
1201
1203 if (!Search(&foundPos, start, oldText, direction, caseSensitive)) {
1204 return kFALSE;
1205 }
1206
1208 delEnd.fY = foundPos.fY;
1209 delEnd.fX = foundPos.fX + strlen(oldText) - 1;
1212 return kTRUE;
1213}
1214
1215////////////////////////////////////////////////////////////////////////////////
1216/// Set fLongestLine.
1217
1219{
1220 Long_t line_count = 0;
1222 fColCount = 0;
1223 while (travel) {
1224 if ((Long_t)travel->fLength > fColCount) {
1225 fColCount = travel->fLength;
1227 }
1228 travel = travel->fNext;
1229 line_count++;
1230 }
1231}
1232
1233////////////////////////////////////////////////////////////////////////////////
1234/// Returns content as ROOT string
1235
1237{
1238 TString ret;
1239
1240 Long_t line_count = 0;
1242 fColCount = 0;
1243
1244 while (travel) {
1245 if ((Long_t)travel->fLength > fColCount) {
1246 fColCount = travel->fLength;
1248 }
1249 char *txt = travel->GetText();
1250 ret += txt;
1251 travel = travel->fNext;
1252 if (travel) ret += '\n';
1253 line_count++;
1254 }
1255
1256 return ret;
1257}
#define c(i)
Definition RSha256.hxx:101
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
const Int_t kMaxLen
const Int_t kMaxLen
Definition TGText.cxx:39
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char text
T1 fFirst
Definition X11Events.mm:86
Long_t fX
x position
Definition TGDimension.h:56
Long_t fY
y position
Definition TGDimension.h:57
virtual ~TGTextLine()
Delete a line of text.
Definition TGText.cxx:115
TGTextLine * fPrev
previous line
Definition TGText.h:28
char * fString
line of text
Definition TGText.h:26
void DelChar(ULong_t pos)
Delete a character from the line.
Definition TGText.cxx:262
void InsChar(ULong_t pos, char character)
Insert a character at the specified position.
Definition TGText.cxx:281
char GetChar(ULong_t pos)
Get a character at the specified position from the line.
Definition TGText.cxx:302
ULong_t GetLineLength()
Definition TGText.h:41
char * GetText() const
Definition TGText.h:46
char * GetWord(ULong_t pos)
Get word at position. Returned string must be deleted.
Definition TGText.cxx:203
void InsText(ULong_t pos, const char *text)
Insert text in line starting at position pos.
Definition TGText.cxx:160
TGTextLine * fNext
next line
Definition TGText.h:29
void Clear()
Clear a line of text.
Definition TGText.cxx:124
TGTextLine()
Create empty line of text (default ctor).
Definition TGText.cxx:46
void DelText(ULong_t pos, ULong_t length)
Delete length chars from line starting at position pos.
Definition TGText.cxx:135
ULong_t fLength
length of line
Definition TGText.h:27
char * GetText(ULong_t pos, ULong_t length)
Get length characters from line starting at pos.
Definition TGText.cxx:183
TGTextLine & operator=(const TGTextLine &)
assignment operator
Definition TGText.cxx:98
A TGText is a multi line text buffer.
Definition TGText.h:57
Bool_t InsChar(TGLongPosition pos, char c)
Insert character c at the specified position pos.
Definition TGText.cxx:705
void ReTab(Long_t row)
Redo all tabs in a line. Needed after a new tab is inserted.
Definition TGText.cxx:1085
virtual ~TGText()
Destroy text buffer.
Definition TGText.cxx:395
Long_t fColCount
number of columns in current line
Definition TGText.h:66
Bool_t AddText(TGText *text)
Add another text buffer to this buffer.
Definition TGText.cxx:909
TGTextLine * fFirst
first line of text
Definition TGText.h:62
Bool_t DelText(TGLongPosition start, TGLongPosition end)
Delete text between start and end positions.
Definition TGText.cxx:734
TString fFilename
name of opened file ("" if open buffer)
Definition TGText.h:60
TGText()
Create default (empty) text buffer.
Definition TGText.cxx:361
Long_t fLongestLine
length of longest line
Definition TGText.h:67
Long_t fRowCount
number of rows
Definition TGText.h:65
Bool_t fIsSaved
false if text needs to be saved
Definition TGText.h:61
void LongestLine()
Set fLongestLine.
Definition TGText.cxx:1218
Bool_t Search(TGLongPosition *foundPos, TGLongPosition start, const char *searchString, Bool_t direction, Bool_t caseSensitive)
Search for string searchString starting at the specified position going in forward (direction = true)...
Definition TGText.cxx:1141
Bool_t DelLine(ULong_t pos)
Delete specified row. Returns false if row does not exist.
Definition TGText.cxx:962
Bool_t Save(const char *fn)
Save text buffer to file fn.
Definition TGText.cxx:608
Bool_t Replace(TGLongPosition start, const char *oldText, const char *newText, Bool_t direction, Bool_t caseSensitive)
Replace oldText by newText. Returns false if nothing replaced.
Definition TGText.cxx:1195
Bool_t InsLine(ULong_t row, const char *string)
Insert string before specified position.
Definition TGText.cxx:926
Bool_t SetCurrentRow(Long_t row)
Make specified row the current row.
Definition TGText.cxx:1053
Long_t fCurrentRow
current row number
Definition TGText.h:64
Bool_t DelChar(TGLongPosition pos)
Delete character at specified position pos.
Definition TGText.cxx:689
Bool_t BreakLine(TGLongPosition pos)
Break line at position pos. Returns false if pos is not valid.
Definition TGText.cxx:1006
Bool_t InsText(TGLongPosition pos, const char *buf)
Insert single line at specified position.
Definition TGText.cxx:886
char * GetLine(TGLongPosition pos, ULong_t length)
Return string at position pos.
Definition TGText.cxx:995
TGTextLine * fCurrent
current line
Definition TGText.h:63
char GetChar(TGLongPosition pos)
Get character a position pos. If character not valid return -1.
Definition TGText.cxx:721
Bool_t Load(const char *fn, Long_t startpos=0, Long_t length=-1)
Load text from file fn.
Definition TGText.cxx:429
Bool_t LoadBuffer(const char *txtbuf)
Load a 0 terminated buffer. Lines will be split at ' '.
Definition TGText.cxx:511
void Clear()
Clear text buffer.
Definition TGText.cxx:404
Bool_t Append(const char *fn)
Append buffer to file fn.
Definition TGText.cxx:649
Long_t GetLineLength(Long_t row)
Get length of specified line. Returns -1 if row does not exist.
Definition TGText.cxx:1041
void Init()
Common initialization method.
Definition TGText.cxx:347
TString AsString()
Returns content as ROOT string.
Definition TGText.cxx:1236
TGText & operator=(const TGText &)
assignment operator
Definition TGText.cxx:329
Basic string class.
Definition TString.h:138
@ kIgnoreCase
Definition TString.h:285
@ kExact
Definition TString.h:285
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:659
TLine * line
Double_t x[n]
Definition legend1.C:17