37 const Int_t kMaxLen = 8000;
45 TGTextLine::TGTextLine()
55 TGTextLine::TGTextLine(TGTextLine *line)
57 fLength = line->GetLineLength();
60 fString = line->GetText(0, line->GetLineLength());
67 TGTextLine::TGTextLine(
const char *
string)
70 fLength = strlen(
string);
71 fString =
new char[fLength+1];
72 strncpy(fString,
string, fLength);
84 TGTextLine::TGTextLine(
const TGTextLine& tl) : fLength(tl.fLength),
85 fPrev(tl.fPrev), fNext(tl.fNext)
89 fString =
new char[fLength+1];
90 strncpy(fString, tl.fString, fLength);
98 TGTextLine& TGTextLine::operator=(
const TGTextLine& 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;
115 TGTextLine::~TGTextLine()
124 void TGTextLine::Clear()
135 void TGTextLine::DelText(ULong_t pos, ULong_t length)
137 if (fLength == 0 || pos >= fLength)
139 if (pos+length > fLength)
140 length = fLength - pos;
142 if (fLength - length <= 0) {
148 char *newstring =
new char[fLength - length+1];
149 strncpy(newstring, fString, (UInt_t)pos);
150 strncpy(newstring+pos, fString+pos+length, UInt_t(fLength-pos-length));
153 fLength = fLength - length;
154 fString[fLength] =
'\0';
160 void TGTextLine::InsText(ULong_t pos,
const char *text)
162 if (pos > fLength || !text)
165 char *newstring =
new char[strlen(text)+fLength+1];
167 strncpy(newstring, fString, (UInt_t)pos);
169 strcpy(newstring+pos, text);
170 if (fString != 0 && fLength - pos > 0)
171 strncpy(newstring+pos+strlen(text), fString+pos, UInt_t(fLength-pos));
172 fLength = fLength + strlen(text);
175 fString[fLength] =
'\0';
183 char *TGTextLine::GetText(ULong_t pos, ULong_t length)
185 if (pos >= fLength) {
189 if (pos + length > (ULong_t)fString) {
190 length = fLength - pos;
193 char *retstring =
new char[length+1];
194 retstring[length] =
'\0';
195 strncpy(retstring, fString+pos, (UInt_t)length);
203 char *TGTextLine::GetWord(ULong_t pos)
205 if (pos >= fLength) {
209 Int_t start = (Int_t)pos;
210 UInt_t end = (UInt_t)pos;
211 UInt_t i = (UInt_t)pos;
213 if (fString[i] ==
' ' || fString[i] ==
'\t') {
215 if (fString[start] ==
' ' || fString[start] ==
'\t') --start;
219 while (end < fLength) {
220 if (fString[end] ==
' ' || fString[end] ==
'\t') ++end;
223 }
else if (isalnum(fString[i])) {
225 if (isalnum(fString[start])) --start;
229 while (end < fLength) {
230 if (isalnum(fString[end])) ++end;
235 if (isalnum(fString[start]) || fString[start] ==
' ' || fString[start] ==
'\t') {
242 while (end < fLength) {
243 if (isalnum(fString[end]) || fString[end] ==
' ' || fString[end] ==
'\t') {
251 UInt_t length = UInt_t(end - start);
252 char *retstring =
new char[length+1];
253 retstring[length] =
'\0';
254 strncpy(retstring, fString+start, length);
262 void TGTextLine::DelChar(ULong_t pos)
265 if ((fLength <= 0) || (pos > fLength))
267 newstring =
new char[fLength];
268 strncpy(newstring, fString, (UInt_t)pos-1);
270 strncpy(newstring+pos-1, fString+pos, UInt_t(fLength-pos+1));
272 newstring[pos-1] = 0;
281 void TGTextLine::InsChar(ULong_t pos,
char character)
286 newstring =
new char[fLength+2];
287 newstring[fLength+1] =
'\0';
289 strncpy (newstring, fString, (UInt_t)pos);
290 newstring[pos] = character;
291 if (fLength - pos > 0)
292 strncpy(newstring+pos+1, fString+pos, UInt_t(fLength-pos));
302 char TGTextLine::GetChar(ULong_t pos)
304 if ((fLength <= 0) || (pos >= fLength))
315 TGText::TGText(
const TGText& gt) :
316 fFilename(gt.fFilename),
317 fIsSaved(gt.fIsSaved),
319 fCurrent(gt.fCurrent),
320 fCurrentRow(gt.fCurrentRow),
321 fRowCount(gt.fRowCount),
322 fColCount(gt.fColCount),
323 fLongestLine(gt.fLongestLine)
330 TGText& TGText::operator=(
const TGText& gt)
333 fFilename=gt.fFilename;
334 fIsSaved=gt.fIsSaved;
336 fCurrent=gt.fCurrent;
337 fCurrentRow=gt.fCurrentRow;
338 fRowCount=gt.fRowCount;
339 fColCount=gt.fColCount;
340 fLongestLine=gt.fLongestLine;
350 fFirst =
new TGTextLine;
370 TGText::TGText(TGText *text)
372 TGLongPosition pos, end;
375 end.fY = text->RowCount() - 1;
376 end.fX = text->GetLineLength(end.fY) - 1;
378 InsText(pos, text, pos, end);
384 TGText::TGText(
const char *
string)
390 InsText(pos,
string);
407 TGTextLine *travel = fFirst->fNext;
408 TGTextLine *toDelete;
409 while (travel != 0) {
411 travel = travel->fNext;
430 Bool_t TGText::Load(
const char *fn, Long_t startpos, Long_t length)
432 Bool_t isFirst = kTRUE;
433 Bool_t finished = kFALSE;
434 Long_t count, charcount, i, cnt;
436 char *buf, c, *src, *dst, *buffer, *buf2;
437 TGTextLine *travel, *temp;
441 if (!(fp = fopen(fn,
"r")))
return kFALSE;
442 buf =
new char[kMaxLen];
444 fseek(fp, startpos, SEEK_SET);
446 while (fgets(buf, kMaxLen, fp)) {
447 if ((length != -1) && (charcount+(Int_t)strlen(buf) > length)) {
448 count = length - charcount;
452 charcount += strlen(buf);
453 buf2 =
new char[count+1];
458 while ((c = *src++)) {
460 if (c == 0x0D || c == 0x0A)
463 else if (c == 0x09) {
465 while (((dst-buf2) & 0x7) && (cnt++ < count-1))
469 if (cnt++ >= count-1)
break;
472 temp =
new TGTextLine;
473 const size_t bufferSize = strlen(buf2)+1;
474 buffer =
new char[bufferSize];
475 strlcpy(buffer, buf2, bufferSize);
476 temp->fLength = strlen(buf2);
477 temp->fString = buffer;
478 temp->fNext = temp->fPrev = 0;
486 travel->fNext = temp;
487 temp->fPrev = travel;
488 travel = travel->fNext;
512 Bool_t TGText::LoadBuffer(
const char *txtbuf)
514 Bool_t isFirst = kTRUE;
515 Bool_t finished = kFALSE, lastnl = kFALSE;
517 TGTextLine *travel, *temp;
518 char *buf, c, *src, *dst, *buffer, *buf2, *s;
519 const char *tbuf = txtbuf;
523 if (!tbuf || !tbuf[0])
526 buf =
new char[kMaxLen];
529 if ((s = (
char*)strchr(tbuf,
'\n'))) {
530 if (s-tbuf+1 >= kMaxLen-1) {
531 strncpy(buf, tbuf, kMaxLen-2);
532 buf[kMaxLen-2] =
'\n';
535 strncpy(buf, tbuf, s-tbuf+1);
540 strncpy(buf, tbuf, kMaxLen-1);
545 buf2 =
new char[kMaxLen+1];
546 buf2[kMaxLen] =
'\0';
550 while ((c = *src++)) {
552 if (c == 0x0D || c == 0x0A)
555 else if (c == 0x09) {
557 while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1))
561 if (cnt++ >= kMaxLen-1)
break;
564 temp =
new TGTextLine;
565 const size_t bufferSize = strlen(buf2) + 1;
566 buffer =
new char[bufferSize];
567 strlcpy(buffer, buf2, bufferSize);
568 temp->fLength = strlen(buf2);
569 temp->fString = buffer;
570 temp->fNext = temp->fPrev = 0;
578 travel->fNext = temp;
579 temp->fPrev = travel;
580 travel = travel->fNext;
586 if (!lastnl && !*tbuf && *(tbuf-1) ==
'\n') {
591 if (!finished && strlen(tbuf))
609 Bool_t TGText::Save(
const char *fn)
612 TGTextLine *travel = fFirst;
614 if (!(fp = fopen(fn,
"w")))
return kFALSE;
618 buffer =
new char[travel->fLength+2];
619 strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
620 buffer[travel->fLength] =
'\n';
621 buffer[travel->fLength+1] =
'\0';
622 while (buffer[i] !=
'\0') {
623 if (buffer[i] ==
'\t') {
625 while (buffer[j] == 16)
628 strcpy(buffer+i+1, buffer+j);
632 if (fputs(buffer, fp) == EOF) {
638 travel = travel->fNext;
650 Bool_t TGText::Append(
const char *fn)
653 TGTextLine *travel = fFirst;
655 if (!(fp = fopen(fn,
"a")))
return kFALSE;
659 buffer =
new char[travel->fLength+2];
660 strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
661 buffer[travel->fLength] =
'\n';
662 buffer[travel->fLength+1] =
'\0';
663 while (buffer[i] !=
'\0') {
664 if (buffer[i] ==
'\t') {
666 while (buffer[j] == 16 && buffer[j] !=
'\0')
669 strcpy(buffer+i+1, buffer+j);
673 if (fputs(buffer, fp) == EOF) {
679 travel = travel->fNext;
690 Bool_t TGText::DelChar(TGLongPosition pos)
692 if ((pos.fY >= fRowCount) || (pos.fY < 0))
695 if (!SetCurrentRow(pos.fY))
return kFALSE;
696 fCurrent->DelChar(pos.fX);
706 Bool_t TGText::InsChar(TGLongPosition pos,
char c)
708 if ((pos.fY >= fRowCount) || (pos.fY < 0) || (pos.fX < 0))
711 if (!SetCurrentRow(pos.fY))
return kFALSE;
712 fCurrent->InsChar(pos.fX, c);
722 char TGText::GetChar(TGLongPosition pos)
724 if (pos.fY >= fRowCount)
727 if (!SetCurrentRow(pos.fY))
return -1;
728 return fCurrent->GetChar(pos.fX);
735 Bool_t TGText::DelText(TGLongPosition start, TGLongPosition end)
737 if ((start.fY < 0) || (start.fY >= fRowCount) ||
738 (end.fY < 0) || (end.fY >= fRowCount)) {
742 if ((end.fX < 0) || (end.fX > GetLineLength(end.fY))) {
748 if (!SetCurrentRow(start.fY))
return kFALSE;
750 if (start.fY == end.fY) {
751 fCurrent->DelText(start.fX, end.fX-start.fX+1);
754 fCurrent->DelText(start.fX, fCurrent->fLength-start.fX);
755 SetCurrentRow(fCurrentRow+1);
756 for (Long_t i = start.fY+1; i < end.fY; i++) {
757 DelLine(fCurrentRow);
760 tempbuffer = fCurrent->GetText(end.fX+1, fCurrent->fLength-end.fX-1);
761 DelLine(fCurrentRow);
762 SetCurrentRow(start.fY);
764 fCurrent->InsText(fCurrent->GetLineLength(), tempbuffer);
765 delete [] tempbuffer;
767 if (fCurrent->fNext) {
768 fCurrent->InsText(fCurrent->fLength, fCurrent->fNext->fString);
769 DelLine(fCurrentRow+1);
770 SetCurrentRow(start.fY);
784 Bool_t TGText::InsText(TGLongPosition ins_pos, TGText *src,
785 TGLongPosition start_src, TGLongPosition end_src)
799 if (ins_pos.fY > fRowCount)
806 TGTextLine *following;
808 if (ins_pos.fY == fRowCount) {
809 pos.fY = fRowCount - 1;
810 pos.fX = GetLineLength(pos.fY);
814 if (!SetCurrentRow(ins_pos.fY))
return kFALSE;
818 restString = fCurrent->GetText(ins_pos.fX, fCurrent->fLength - ins_pos.fX);
819 fCurrent->DelText(ins_pos.fX, fCurrent->fLength - ins_pos.fX);
820 following = fCurrent->fNext;
822 if (start_src.fY == end_src.fY) {
823 len = end_src.fX - start_src.fX+1;
825 len = src->GetLineLength(start_src.fY) - start_src.fX;
829 lineString = src->GetLine(start_src, len);
830 fCurrent->InsText(ins_pos.fX, lineString);
831 delete [] lineString;
834 pos.fY = start_src.fY+1;
836 for ( ; pos.fY < end_src.fY; pos.fY++) {
837 Int_t llen = src->GetLineLength(pos.fY);
838 lineString = src->GetLine(pos, llen > 0 ? llen : 0);
839 fCurrent->fNext =
new TGTextLine(lineString);
840 fCurrent->fNext->fPrev = fCurrent;
841 fCurrent = fCurrent->fNext;
844 delete [] lineString;
847 if (start_src.fY != end_src.fY) {
850 lineString = src->GetLine(pos, end_src.fX+1);
851 fCurrent->fNext =
new TGTextLine(lineString);
852 fCurrent->fNext->fPrev = fCurrent;
853 fCurrent = fCurrent->fNext;
856 delete [] lineString;
861 if (ins_pos.fX == 0) {
862 fCurrent->fNext =
new TGTextLine(restString);
863 fCurrent->fNext->fPrev = fCurrent;
864 fCurrent = fCurrent->fNext;
869 fCurrent->InsText(fCurrent->fLength, restString);
870 delete [] restString;
873 fCurrent->fNext = following;
874 if (fCurrent->fNext) {
875 fCurrent->fNext->fPrev = fCurrent;
887 Bool_t TGText::InsText(TGLongPosition pos,
const char *buffer)
889 if (pos.fY < 0 || pos.fY > fRowCount) {
893 if (pos.fY == fRowCount) {
894 SetCurrentRow(fRowCount-1);
895 fCurrent->fNext =
new TGTextLine(buffer);
896 fCurrent->fNext->fPrev = fCurrent;
899 SetCurrentRow(pos.fY);
900 fCurrent->InsText(pos.fX, buffer);
910 Bool_t TGText::AddText(TGText *text)
912 TGLongPosition end, start_src, end_src;
916 start_src.fX = start_src.fY = 0;
917 end_src.fY = text->RowCount()-1;
918 end_src.fX = text->GetLineLength(end_src.fY)-1;
920 return InsText(end, text, start_src, end_src);
927 Bool_t TGText::InsLine(ULong_t pos,
const char *
string)
929 TGTextLine *previous, *newline;
930 if ((Long_t)pos > fRowCount) {
933 if ((Long_t)pos < fRowCount) {
936 SetCurrentRow(fRowCount-1);
939 if (!fCurrent)
return kFALSE;
941 previous = fCurrent->fPrev;
942 newline =
new TGTextLine(
string);
943 newline->fPrev = previous;
945 previous->fNext = newline;
950 newline->fNext = fCurrent;
951 fCurrent->fPrev = newline;
963 Bool_t TGText::DelLine(ULong_t pos)
965 if (!SetCurrentRow(pos) || (fRowCount == 1)) {
969 TGTextLine *travel = fCurrent;
970 if (travel == fFirst) {
971 fFirst = fFirst->fNext;
974 travel->fPrev->fNext = travel->fNext;
976 travel->fNext->fPrev = travel->fPrev;
977 fCurrent = fCurrent->fNext;
979 fCurrent = fCurrent->fPrev;
996 char *TGText::GetLine(TGLongPosition pos, ULong_t length)
998 if (SetCurrentRow(pos.fY)) {
999 return fCurrent->GetText(pos.fX, length);
1007 Bool_t TGText::BreakLine(TGLongPosition pos)
1009 if (!SetCurrentRow(pos.fY))
1011 if ((pos.fX < 0) || (pos.fX > (Long_t)fCurrent->fLength))
1016 if (pos.fX < (Long_t)fCurrent->fLength) {
1017 tempbuffer = fCurrent->GetText(pos.fX, fCurrent->fLength-pos.fX);
1018 temp =
new TGTextLine(tempbuffer);
1019 fCurrent->DelText(pos.fX, fCurrent->fLength - pos.fX);
1020 delete [] tempbuffer;
1022 temp =
new TGTextLine;
1024 temp->fPrev = fCurrent;
1025 temp->fNext = fCurrent->fNext;
1026 fCurrent->fNext = temp;
1028 temp->fNext->fPrev = temp;
1034 fCurrent = fCurrent->fNext;
1042 Long_t TGText::GetLineLength(Long_t row)
1044 if (!SetCurrentRow(row)) {
1047 return (Long_t)fCurrent->GetLineLength();
1054 Bool_t TGText::SetCurrentRow(Long_t row)
1057 if ((row < 0) || (row >= fRowCount)) {
1060 if (row > fCurrentRow) {
1061 for (count = fCurrentRow; count < row; count++) {
1062 if (!fCurrent->fNext) {
1063 fCurrentRow = count;
1066 fCurrent = fCurrent->fNext;
1069 if (fCurrentRow == row)
1071 for (count = fCurrentRow; count > row; count--) {
1072 if (!fCurrent->fPrev) {
1073 fCurrentRow = count;
1076 fCurrent = fCurrent->fPrev;
1086 void TGText::ReTab(Long_t row)
1088 if (!SetCurrentRow(row)) {
1096 buffer = fCurrent->fString;
1097 while (buffer[i] !=
'\0') {
1098 if (buffer[i] ==
'\t') {
1100 while (buffer[j] == 16 && buffer[j] !=
'\0') {
1104 strcpy(buffer+i+1, buffer+j);
1109 char c, *src, *dst, *buf2;
1112 buf2 =
new char[kMaxLen+1];
1113 buf2[kMaxLen] =
'\0';
1117 while ((c = *src++)) {
1121 while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1)) {
1127 if (cnt++ >= kMaxLen-1)
break;
1131 fCurrent->fString = buf2;
1132 fCurrent->fLength = strlen(buf2);
1142 Bool_t TGText::Search(TGLongPosition *foundPos, TGLongPosition start,
1143 const char *searchString,
1144 Bool_t direction, Bool_t caseSensitive)
1146 if (!SetCurrentRow(start.fY))
1153 TString s = fCurrent->fString;
1154 x = s.Index(searchString, (Ssiz_t)start.fX,
1155 caseSensitive ? TString::kExact : TString::kIgnoreCase);
1158 foundPos->fY = fCurrentRow;
1161 if (!SetCurrentRow(fCurrentRow+1))
1167 TString s = fCurrent->fString;
1168 for (
int i = (
int)start.fX; i >= 0; i--) {
1169 x = s.Index(searchString, (Ssiz_t)i,
1170 caseSensitive ? TString::kExact : TString::kIgnoreCase);
1171 if (x >= start.fX) {
1181 foundPos->fY = fCurrentRow;
1184 if (!SetCurrentRow(fCurrentRow-1)) {
1187 start.fX = fCurrent->fLength;
1196 Bool_t TGText::Replace(TGLongPosition start,
const char *oldText,
const char *newText,
1197 Bool_t direction, Bool_t caseSensitive)
1199 if (!SetCurrentRow(start.fY)) {
1203 TGLongPosition foundPos;
1204 if (!Search(&foundPos, start, oldText, direction, caseSensitive)) {
1208 TGLongPosition delEnd;
1209 delEnd.fY = foundPos.fY;
1210 delEnd.fX = foundPos.fX + strlen(oldText) - 1;
1211 DelText(foundPos, delEnd);
1212 InsText(foundPos, newText);
1219 void TGText::LongestLine()
1221 Long_t line_count = 0;
1222 TGTextLine *travel = fFirst;
1225 if ((Long_t)travel->fLength > fColCount) {
1226 fColCount = travel->fLength;
1227 fLongestLine = line_count;
1229 travel = travel->fNext;
1237 TString TGText::AsString()
1241 Long_t line_count = 0;
1242 TGTextLine *travel = fFirst;
1246 if ((Long_t)travel->fLength > fColCount) {
1247 fColCount = travel->fLength;
1248 fLongestLine = line_count;
1250 ret += travel->GetText();
1251 travel = travel->fNext;
1252 if (travel) ret +=
'\n';