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