00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "TGText.h"
00035 #include <ctype.h>
00036
00037 const Int_t kMaxLen = 8000;
00038
00039
00040 ClassImp(TGTextLine)
00041
00042
00043 TGTextLine::TGTextLine()
00044 {
00045
00046
00047 fLength = 0;
00048 fString = 0;
00049 fPrev = fNext = 0;
00050 }
00051
00052
00053 TGTextLine::TGTextLine(TGTextLine *line)
00054 {
00055
00056
00057 fLength = line->GetLineLength();
00058 fString = 0;
00059 if (fLength > 0)
00060 fString = line->GetText(0, line->GetLineLength());
00061 fPrev = fNext = 0;
00062 }
00063
00064
00065 TGTextLine::TGTextLine(const char *string)
00066 {
00067
00068
00069 if (string) {
00070 fLength = strlen(string);
00071 fString = new char[fLength+1];
00072 strncpy(fString, string, fLength);
00073 fString[fLength] = 0;
00074 } else {
00075 fLength = 0;
00076 fString = 0;
00077 }
00078 fPrev = fNext = 0;
00079 }
00080
00081
00082 TGTextLine::TGTextLine(const TGTextLine& tl) :
00083 fString(tl.fString),
00084 fLength(tl.fLength),
00085 fPrev(tl.fPrev),
00086 fNext(tl.fNext)
00087 {
00088
00089 }
00090
00091
00092 TGTextLine& TGTextLine::operator=(const TGTextLine& tl)
00093 {
00094
00095 if(this!=&tl) {
00096 fString=tl.fString;
00097 fLength=tl.fLength;
00098 fPrev=tl.fPrev;
00099 fNext=tl.fNext;
00100 }
00101 return *this;
00102 }
00103
00104
00105 TGTextLine::~TGTextLine()
00106 {
00107
00108
00109 if (fString)
00110 delete [] fString;
00111 }
00112
00113
00114 void TGTextLine::Clear()
00115 {
00116
00117
00118 if (fString)
00119 delete [] fString;
00120 fString = 0;
00121 fLength = 0;
00122 }
00123
00124
00125 void TGTextLine::DelText(ULong_t pos, ULong_t length)
00126 {
00127
00128
00129 if (fLength == 0 || pos >= fLength)
00130 return;
00131 if (pos+length > fLength)
00132 length = fLength - pos;
00133
00134 if (fLength - length <= 0) {
00135 delete [] fString;
00136 fLength = 0;
00137 fString = 0;
00138 return;
00139 }
00140 char *newstring = new char[fLength - length+1];
00141 strncpy(newstring, fString, (UInt_t)pos);
00142 strncpy(newstring+pos, fString+pos+length, UInt_t(fLength-pos-length));
00143 delete [] fString;
00144 fString = newstring;
00145 fLength = fLength - length;
00146 fString[fLength] = '\0';
00147 }
00148
00149
00150 void TGTextLine::InsText(ULong_t pos, const char *text)
00151 {
00152
00153
00154 if (pos > fLength || !text)
00155 return;
00156
00157 char *newstring = new char[strlen(text)+fLength+1];
00158 if (fString != 0)
00159 strncpy(newstring, fString, (UInt_t)pos);
00160 strcpy(newstring+pos, text);
00161 if (fString != 0 && fLength - pos > 0)
00162 strncpy(newstring+pos+strlen(text), fString+pos, UInt_t(fLength-pos));
00163 fLength = fLength + strlen(text);
00164 delete [] fString;
00165 fString = newstring;
00166 fString[fLength] ='\0';
00167 }
00168
00169
00170 char *TGTextLine::GetText(ULong_t pos, ULong_t length)
00171 {
00172
00173
00174
00175
00176 if (pos >= fLength) {
00177 return 0;
00178 }
00179
00180 if (pos + length > (ULong_t)fString) {
00181 length = fLength - pos;
00182 }
00183
00184 char *retstring = new char[length+1];
00185 retstring[length] = '\0';
00186 strncpy(retstring, fString+pos, (UInt_t)length);
00187
00188 return retstring;
00189 }
00190
00191
00192 char *TGTextLine::GetWord(ULong_t pos)
00193 {
00194
00195
00196 if (pos >= fLength) {
00197 return 0;
00198 }
00199
00200 Int_t start = (Int_t)pos;
00201 UInt_t end = (UInt_t)pos;
00202 UInt_t i = (UInt_t)pos;
00203
00204 if (fString[i] == ' ' || fString[i] == '\t') {
00205 while (start >= 0) {
00206 if (fString[start] == ' ' || fString[start] == '\t') --start;
00207 else break;
00208 }
00209 ++start;
00210 while (end < fLength) {
00211 if (fString[end] == ' ' || fString[end] == '\t') ++end;
00212 else break;
00213 }
00214 } else if (isalnum(fString[i])) {
00215 while (start >= 0) {
00216 if (isalnum(fString[start])) --start;
00217 else break;
00218 }
00219 ++start;
00220 while (end < fLength) {
00221 if (isalnum(fString[end])) ++end;
00222 else break;
00223 }
00224 } else {
00225 while (start >= 0) {
00226 if (isalnum(fString[start]) || fString[start] == ' ' || fString[start] == '\t') {
00227 break;
00228 } else {
00229 --start;
00230 }
00231 }
00232 ++start;
00233 while (end < fLength) {
00234 if (isalnum(fString[end]) || fString[end] == ' ' || fString[end] == '\t') {
00235 break;
00236 } else {
00237 ++end;
00238 }
00239 }
00240 }
00241
00242 UInt_t length = UInt_t(end - start);
00243 char *retstring = new char[length+1];
00244 retstring[length] = '\0';
00245 strncpy(retstring, fString+start, length);
00246
00247 return retstring;
00248 }
00249
00250
00251 void TGTextLine::DelChar(ULong_t pos)
00252 {
00253
00254
00255 char *newstring;
00256 if ((fLength <= 0) || (pos > fLength))
00257 return;
00258 newstring = new char[fLength];
00259 strncpy(newstring, fString, (UInt_t)pos-1);
00260 if (pos < fLength)
00261 strncpy(newstring+pos-1, fString+pos, UInt_t(fLength-pos+1));
00262 else
00263 newstring[pos-1] = 0;
00264 delete [] fString;
00265 fString = newstring;
00266 fLength--;
00267 }
00268
00269
00270 void TGTextLine::InsChar(ULong_t pos, char character)
00271 {
00272
00273
00274 char *newstring;
00275 if (pos > fLength)
00276 return;
00277 newstring = new char[fLength+2];
00278 newstring[fLength+1] = '\0';
00279 if (fLength > 0)
00280 strncpy (newstring, fString, (UInt_t)pos);
00281 newstring[pos] = character;
00282 if (fLength - pos > 0)
00283 strncpy(newstring+pos+1, fString+pos, UInt_t(fLength-pos));
00284 delete [] fString;
00285 fString = newstring;
00286 fLength++;
00287 }
00288
00289
00290 char TGTextLine::GetChar(ULong_t pos)
00291 {
00292
00293
00294
00295 if ((fLength <= 0) || (pos >= fLength))
00296 return -1;
00297 return fString[pos];
00298 }
00299
00300
00301 ClassImp(TGText)
00302
00303
00304 TGText::TGText(const TGText& gt) :
00305 fFilename(gt.fFilename),
00306 fIsSaved(gt.fIsSaved),
00307 fFirst(gt.fFirst),
00308 fCurrent(gt.fCurrent),
00309 fCurrentRow(gt.fCurrentRow),
00310 fRowCount(gt.fRowCount),
00311 fColCount(gt.fColCount),
00312 fLongestLine(gt.fLongestLine)
00313 {
00314
00315 }
00316
00317
00318 TGText& TGText::operator=(const TGText& gt)
00319 {
00320
00321 if(this!=>) {
00322 fFilename=gt.fFilename;
00323 fIsSaved=gt.fIsSaved;
00324 fFirst=gt.fFirst;
00325 fCurrent=gt.fCurrent;
00326 fCurrentRow=gt.fCurrentRow;
00327 fRowCount=gt.fRowCount;
00328 fColCount=gt.fColCount;
00329 fLongestLine=gt.fLongestLine;
00330 }
00331 return *this;
00332 }
00333
00334
00335 void TGText::Init()
00336 {
00337
00338
00339 fFirst = new TGTextLine;
00340 fCurrent = fFirst;
00341 fCurrentRow = 0;
00342 fColCount = 0;
00343 fRowCount = 1;
00344 fLongestLine = 0;
00345 fIsSaved = kTRUE;
00346 }
00347
00348
00349 TGText::TGText()
00350 {
00351
00352
00353 Init();
00354 }
00355
00356
00357 TGText::TGText(TGText *text)
00358 {
00359
00360
00361 TGLongPosition pos, end;
00362
00363 pos.fX = pos.fY = 0;
00364 end.fY = text->RowCount() - 1;
00365 end.fX = text->GetLineLength(end.fY) - 1;
00366 Init();
00367 InsText(pos, text, pos, end);
00368 }
00369
00370
00371 TGText::TGText(const char *string)
00372 {
00373
00374
00375 TGLongPosition pos;
00376
00377 pos.fX = pos.fY = 0;
00378 Init();
00379 InsText(pos, string);
00380 }
00381
00382
00383 TGText::~TGText()
00384 {
00385
00386
00387 Clear();
00388 delete fFirst;
00389 }
00390
00391
00392 void TGText::Clear()
00393 {
00394
00395
00396 TGTextLine *travel = fFirst->fNext;
00397 TGTextLine *toDelete;
00398 while (travel != 0) {
00399 toDelete = travel;
00400 travel = travel->fNext;
00401 delete toDelete;
00402 }
00403 fFirst->Clear();
00404 fFirst->fNext = 0;
00405 fCurrent = fFirst;
00406 fCurrentRow = 0;
00407 fColCount = 0;
00408 fRowCount = 1;
00409 fLongestLine = 0;
00410 fIsSaved = kTRUE;
00411 fFilename = "";
00412 }
00413
00414
00415 Bool_t TGText::Load(const char *fn, Long_t startpos, Long_t length)
00416 {
00417
00418
00419
00420
00421 Bool_t isFirst = kTRUE;
00422 Bool_t finished = kFALSE;
00423 Long_t count, charcount, i, cnt;
00424 FILE *fp;
00425 char *buf, c, *src, *dst, *buffer, *buf2;
00426 TGTextLine *travel, *temp;
00427
00428 travel = fFirst;
00429
00430 if (!(fp = fopen(fn, "r"))) return kFALSE;
00431 buf = new char[kMaxLen];
00432 i = 0;
00433 fseek(fp, startpos, SEEK_SET);
00434 charcount = 0;
00435 while (fgets(buf, kMaxLen, fp)) {
00436 if ((length != -1) && (charcount+(Int_t)strlen(buf) > length)) {
00437 count = length - charcount;
00438 finished = kTRUE;
00439 } else
00440 count = kMaxLen;
00441 charcount += strlen(buf);
00442 buf2 = new char[count+1];
00443 buf2[count] = '\0';
00444 src = buf;
00445 dst = buf2;
00446 cnt = 0;
00447 while ((c = *src++)) {
00448
00449 if (c == 0x0D || c == 0x0A)
00450 break;
00451
00452 else if (c == 0x09) {
00453 *dst++ = '\t';
00454 while (((dst-buf2) & 0x7) && (cnt++ < count-1))
00455 *dst++ = 16;
00456 } else
00457 *dst++ = c;
00458 if (cnt++ >= count-1) break;
00459 }
00460 *dst = '\0';
00461 temp = new TGTextLine;
00462 buffer = new char[strlen(buf2)+1];
00463 strlcpy(buffer, buf2, strlen(buf2)+1);
00464 temp->fLength = strlen(buf2);
00465 temp->fString = buffer;
00466 temp->fNext = temp->fPrev = 0;
00467 if (isFirst) {
00468 delete fFirst;
00469 fFirst = temp;
00470 fCurrent = temp;
00471 travel = fFirst;
00472 isFirst = kFALSE;
00473 } else {
00474 travel->fNext = temp;
00475 temp->fPrev = travel;
00476 travel = travel->fNext;
00477 }
00478 ++i;
00479 delete [] buf2;
00480 if (finished)
00481 break;
00482 }
00483 fclose(fp);
00484 delete [] buf;
00485
00486
00487 fRowCount = i;
00488 if (fRowCount == 0)
00489 fRowCount++;
00490 fIsSaved = kTRUE;
00491 fFilename = fn;
00492 LongestLine();
00493
00494 return kTRUE;
00495 }
00496
00497
00498 Bool_t TGText::LoadBuffer(const char *txtbuf)
00499 {
00500
00501
00502 Bool_t isFirst = kTRUE;
00503 Bool_t finished = kFALSE, lastnl = kFALSE;
00504 Long_t i, cnt;
00505 TGTextLine *travel, *temp;
00506 char *buf, c, *src, *dst, *buffer, *buf2, *s;
00507 const char *tbuf = txtbuf;
00508
00509 travel = fFirst;
00510
00511 if (!tbuf || !strlen(tbuf))
00512 return kFALSE;
00513
00514 buf = new char[kMaxLen];
00515 i = 0;
00516 next:
00517 if ((s = (char*)strchr(tbuf, '\n'))) {
00518 if (s-tbuf+1 >= kMaxLen-1) {
00519 strncpy(buf, tbuf, kMaxLen-2);
00520 buf[kMaxLen-2] = '\n';
00521 buf[kMaxLen-1] = 0;
00522 } else {
00523 strncpy(buf, tbuf, s-tbuf+1);
00524 buf[s-tbuf+1] = 0;
00525 }
00526 tbuf = s+1;
00527 } else {
00528 strncpy(buf, tbuf, kMaxLen-1);
00529 buf[kMaxLen-1] = 0;
00530 finished = kTRUE;
00531 }
00532
00533 buf2 = new char[kMaxLen+1];
00534 buf2[kMaxLen] = '\0';
00535 src = buf;
00536 dst = buf2;
00537 cnt = 0;
00538 while ((c = *src++)) {
00539
00540 if (c == 0x0D || c == 0x0A)
00541 break;
00542
00543 else if (c == 0x09) {
00544 *dst++ = '\t';
00545 while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1))
00546 *dst++ = 16;
00547 } else
00548 *dst++ = c;
00549 if (cnt++ >= kMaxLen-1) break;
00550 }
00551 *dst = '\0';
00552 temp = new TGTextLine;
00553 buffer = new char[strlen(buf2)+1];
00554 strlcpy(buffer, buf2, strlen(buf2)+1);
00555 temp->fLength = strlen(buf2);
00556 temp->fString = buffer;
00557 temp->fNext = temp->fPrev = 0;
00558 if (isFirst) {
00559 delete fFirst;
00560 fFirst = temp;
00561 fCurrent = temp;
00562 travel = fFirst;
00563 isFirst = kFALSE;
00564 } else {
00565 travel->fNext = temp;
00566 temp->fPrev = travel;
00567 travel = travel->fNext;
00568 }
00569 ++i;
00570 delete [] buf2;
00571
00572
00573 if (!lastnl && !*tbuf && *(tbuf-1) == '\n') {
00574 tbuf--;
00575 lastnl = kTRUE;
00576 }
00577
00578 if (!finished && tbuf && strlen(tbuf))
00579 goto next;
00580
00581 delete [] buf;
00582
00583 fRowCount = i;
00584 if (fRowCount == 0)
00585 fRowCount++;
00586 fIsSaved = kTRUE;
00587 fFilename = "";
00588 LongestLine();
00589
00590 return kTRUE;
00591 }
00592
00593
00594 Bool_t TGText::Save(const char *fn)
00595 {
00596
00597
00598 char *buffer;
00599 TGTextLine *travel = fFirst;
00600 FILE *fp;
00601 if (!(fp = fopen(fn, "w"))) return kFALSE;
00602
00603 while (travel) {
00604 ULong_t i = 0;
00605 buffer = new char[travel->fLength+2];
00606 strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
00607 buffer[travel->fLength] = '\n';
00608 buffer[travel->fLength+1] = '\0';
00609 while (buffer[i] != '\0') {
00610 if (buffer[i] == '\t') {
00611 ULong_t j = i+1;
00612 while (buffer[j] == 16)
00613 j++;
00614 strcpy(buffer+i+1, buffer+j);
00615 }
00616 i++;
00617 }
00618 if (fputs(buffer, fp) == EOF) {
00619 delete [] buffer;
00620 fclose(fp);
00621 return kFALSE;
00622 }
00623 delete [] buffer;
00624 travel = travel->fNext;
00625 }
00626 fIsSaved = kTRUE;
00627 fFilename = fn;
00628 fclose(fp);
00629
00630 return kTRUE;
00631 }
00632
00633
00634 Bool_t TGText::Append(const char *fn)
00635 {
00636
00637
00638 char *buffer;
00639 TGTextLine *travel = fFirst;
00640 FILE *fp;
00641 if (!(fp = fopen(fn, "a"))) return kFALSE;
00642
00643 while (travel) {
00644 ULong_t i = 0;
00645 buffer = new char[travel->fLength+2];
00646 strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
00647 buffer[travel->fLength] = '\n';
00648 buffer[travel->fLength+1] = '\0';
00649 while (buffer[i] != '\0') {
00650 if (buffer[i] == '\t') {
00651 ULong_t j = i+1;
00652 while (buffer[j] == 16 && buffer[j] != '\0')
00653 j++;
00654 strcpy(buffer+i+1, buffer+j);
00655 }
00656 i++;
00657 }
00658 if (fputs(buffer, fp) == EOF) {
00659 delete [] buffer;
00660 fclose(fp);
00661 return kFALSE;
00662 }
00663 delete [] buffer;
00664 travel = travel->fNext;
00665 }
00666 fIsSaved = kTRUE;
00667 fclose(fp);
00668
00669 return kTRUE;
00670 }
00671
00672
00673 Bool_t TGText::DelChar(TGLongPosition pos)
00674 {
00675
00676
00677 if ((pos.fY >= fRowCount) || (pos.fY < 0))
00678 return kFALSE;
00679
00680 if (!SetCurrentRow(pos.fY)) return kFALSE;
00681 fCurrent->DelChar(pos.fX);
00682
00683 fIsSaved = kFALSE;
00684 LongestLine();
00685 return kTRUE;
00686 }
00687
00688
00689 Bool_t TGText::InsChar(TGLongPosition pos, char c)
00690 {
00691
00692
00693 if ((pos.fY >= fRowCount) || (pos.fY < 0) || (pos.fX < 0))
00694 return kFALSE;
00695
00696 if (!SetCurrentRow(pos.fY)) return kFALSE;
00697 fCurrent->InsChar(pos.fX, c);
00698
00699 fIsSaved = kFALSE;
00700 LongestLine();
00701 return kTRUE;
00702 }
00703
00704
00705 char TGText::GetChar(TGLongPosition pos)
00706 {
00707
00708
00709 if (pos.fY >= fRowCount)
00710 return -1;
00711
00712 if (!SetCurrentRow(pos.fY)) return -1;
00713 return fCurrent->GetChar(pos.fX);
00714 }
00715
00716
00717 Bool_t TGText::DelText(TGLongPosition start, TGLongPosition end)
00718 {
00719
00720
00721
00722 if ((start.fY < 0) || (start.fY >= fRowCount) ||
00723 (end.fY < 0) || (end.fY >= fRowCount)) {
00724 return kFALSE;
00725 }
00726
00727 if ((end.fX < 0) || (end.fX > GetLineLength(end.fY))) {
00728 return kFALSE;
00729 }
00730
00731 char *tempbuffer;
00732
00733 if (!SetCurrentRow(start.fY)) return kFALSE;
00734
00735 if (start.fY == end.fY) {
00736 fCurrent->DelText(start.fX, end.fX-start.fX+1);
00737 return kTRUE;
00738 }
00739 fCurrent->DelText(start.fX, fCurrent->fLength-start.fX);
00740 SetCurrentRow(fCurrentRow+1);
00741 for (Long_t i = start.fY+1; i < end.fY; i++) {
00742 DelLine(fCurrentRow);
00743 }
00744
00745 tempbuffer = fCurrent->GetText(end.fX+1, fCurrent->fLength-end.fX-1);
00746 DelLine(fCurrentRow);
00747 SetCurrentRow(start.fY);
00748 if (tempbuffer) {
00749 fCurrent->InsText(fCurrent->GetLineLength(), tempbuffer);
00750 delete [] tempbuffer;
00751 } else {
00752 if (fCurrent->fNext) {
00753 fCurrent->InsText(fCurrent->fLength, fCurrent->fNext->fString);
00754 DelLine(fCurrentRow+1);
00755 SetCurrentRow(start.fY);
00756 }
00757 }
00758
00759 fIsSaved = kFALSE;
00760 LongestLine();
00761 return kTRUE;
00762 }
00763
00764
00765 Bool_t TGText::InsText(TGLongPosition ins_pos, TGText *src,
00766 TGLongPosition start_src, TGLongPosition end_src)
00767 {
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 if (ins_pos.fY > fRowCount)
00785 return kFALSE;
00786
00787 TGLongPosition pos;
00788 ULong_t len;
00789 char *lineString;
00790 char *restString;
00791 TGTextLine *following;
00792
00793 if (ins_pos.fY == fRowCount) {
00794 pos.fY = fRowCount - 1;
00795 pos.fX = GetLineLength(pos.fY);
00796 BreakLine(pos);
00797 } else {
00798
00799 if (!SetCurrentRow(ins_pos.fY)) return kFALSE;
00800 }
00801
00802
00803 restString = fCurrent->GetText(ins_pos.fX, fCurrent->fLength - ins_pos.fX);
00804 fCurrent->DelText(ins_pos.fX, fCurrent->fLength - ins_pos.fX);
00805 following = fCurrent->fNext;
00806
00807 if (start_src.fY == end_src.fY) {
00808 len = end_src.fX - start_src.fX+1;
00809 } else {
00810 len = src->GetLineLength(start_src.fY) - start_src.fX;
00811 }
00812
00813 if (len > 0) {
00814 lineString = src->GetLine(start_src, len);
00815 fCurrent->InsText(ins_pos.fX, lineString);
00816 delete [] lineString;
00817 }
00818
00819 pos.fY = start_src.fY+1;
00820 pos.fX = 0;
00821 for ( ; pos.fY < end_src.fY; pos.fY++) {
00822 Int_t llen = src->GetLineLength(pos.fY);
00823 lineString = src->GetLine(pos, llen > 0 ? llen : 0);
00824 fCurrent->fNext = new TGTextLine(lineString);
00825 fCurrent->fNext->fPrev = fCurrent;
00826 fCurrent = fCurrent->fNext;
00827 fRowCount++;
00828 fCurrentRow++;
00829 delete [] lineString;
00830 }
00831
00832 if (start_src.fY != end_src.fY) {
00833 pos.fY = end_src.fY;
00834 pos.fX = 0;
00835 lineString = src->GetLine(pos, end_src.fX+1);
00836 fCurrent->fNext = new TGTextLine(lineString);
00837 fCurrent->fNext->fPrev = fCurrent;
00838 fCurrent = fCurrent->fNext;
00839 fRowCount++;
00840 fCurrentRow++;
00841 delete [] lineString;
00842 }
00843
00844 if (restString) {
00845 #if 0
00846 if (ins_pos.fX == 0) {
00847 fCurrent->fNext = new TGTextLine(restString);
00848 fCurrent->fNext->fPrev = fCurrent;
00849 fCurrent = fCurrent->fNext;
00850 fRowCount++;
00851 fCurrentRow++;
00852 } else
00853 #endif
00854 fCurrent->InsText(fCurrent->fLength, restString);
00855 delete [] restString;
00856 }
00857
00858 fCurrent->fNext = following;
00859 if (fCurrent->fNext) {
00860 fCurrent->fNext->fPrev = fCurrent;
00861 }
00862
00863 LongestLine();
00864 fIsSaved = kFALSE;
00865 return kTRUE;
00866 }
00867
00868
00869 Bool_t TGText::InsText(TGLongPosition pos, const char *buffer)
00870 {
00871
00872
00873
00874 if (pos.fY < 0 || pos.fY > fRowCount) {
00875 return kFALSE;
00876 }
00877
00878 if (pos.fY == fRowCount) {
00879 SetCurrentRow(fRowCount-1);
00880 fCurrent->fNext = new TGTextLine(buffer);
00881 fCurrent->fNext->fPrev = fCurrent;
00882 fRowCount++;
00883 } else {
00884 SetCurrentRow(pos.fY);
00885 fCurrent->InsText(pos.fX, buffer);
00886 }
00887 LongestLine();
00888 fIsSaved = kFALSE;
00889 return kTRUE;
00890 }
00891
00892
00893 Bool_t TGText::AddText(TGText *text)
00894 {
00895
00896
00897 TGLongPosition end, start_src, end_src;
00898
00899 end.fY = fRowCount;
00900 end.fX = 0;
00901 start_src.fX = start_src.fY = 0;
00902 end_src.fY = text->RowCount()-1;
00903 end_src.fX = text->GetLineLength(end_src.fY)-1;
00904 fIsSaved = kFALSE;
00905 return InsText(end, text, start_src, end_src);
00906 }
00907
00908
00909 Bool_t TGText::InsLine(ULong_t pos, const char *string)
00910 {
00911
00912
00913
00914 TGTextLine *previous, *newline;
00915 if ((Long_t)pos > fRowCount) {
00916 return kFALSE;
00917 }
00918 if ((Long_t)pos < fRowCount) {
00919 SetCurrentRow(pos);
00920 } else {
00921 SetCurrentRow(fRowCount-1);
00922 }
00923
00924 if (!fCurrent) return kFALSE;
00925
00926 previous = fCurrent->fPrev;
00927 newline = new TGTextLine(string);
00928 newline->fPrev = previous;
00929 if (previous) {
00930 previous->fNext = newline;
00931 } else {
00932 fFirst = newline;
00933 }
00934
00935 newline->fNext = fCurrent;
00936 fCurrent->fPrev = newline;
00937 fRowCount++;
00938 fCurrentRow++;
00939
00940 LongestLine();
00941 fIsSaved = kFALSE;
00942 return kTRUE;
00943 }
00944
00945
00946 Bool_t TGText::DelLine(ULong_t pos)
00947 {
00948
00949
00950 if (!SetCurrentRow(pos) || (fRowCount == 1)) {
00951 return kFALSE;
00952 }
00953
00954 TGTextLine *travel = fCurrent;
00955 if (travel == fFirst) {
00956 fFirst = fFirst->fNext;
00957 fFirst->fPrev = 0;
00958 } else {
00959 travel->fPrev->fNext = travel->fNext;
00960 if (travel->fNext) {
00961 travel->fNext->fPrev = travel->fPrev;
00962 fCurrent = fCurrent->fNext;
00963 } else {
00964 fCurrent = fCurrent->fPrev;
00965 fCurrentRow--;
00966 }
00967 }
00968 delete travel;
00969
00970 fRowCount--;
00971 fIsSaved = kFALSE;
00972 LongestLine();
00973
00974 return kTRUE;
00975 }
00976
00977
00978 char *TGText::GetLine(TGLongPosition pos, ULong_t length)
00979 {
00980
00981
00982
00983 if (SetCurrentRow(pos.fY)) {
00984 return fCurrent->GetText(pos.fX, length);
00985 }
00986 return 0;
00987 }
00988
00989
00990 Bool_t TGText::BreakLine(TGLongPosition pos)
00991 {
00992
00993
00994 if (!SetCurrentRow(pos.fY))
00995 return kFALSE;
00996 if ((pos.fX < 0) || (pos.fX > (Long_t)fCurrent->fLength))
00997 return kFALSE;
00998
00999 TGTextLine *temp;
01000 char *tempbuffer;
01001 if (pos.fX < (Long_t)fCurrent->fLength) {
01002 tempbuffer = fCurrent->GetText(pos.fX, fCurrent->fLength-pos.fX);
01003 temp = new TGTextLine(tempbuffer);
01004 fCurrent->DelText(pos.fX, fCurrent->fLength - pos.fX);
01005 delete [] tempbuffer;
01006 } else {
01007 temp = new TGTextLine;
01008 }
01009 temp->fPrev = fCurrent;
01010 temp->fNext = fCurrent->fNext;
01011 fCurrent->fNext = temp;
01012 if (temp->fNext) {
01013 temp->fNext->fPrev = temp;
01014 }
01015
01016 fIsSaved = kFALSE;
01017 fRowCount++;
01018 fCurrentRow++;
01019 fCurrent = fCurrent->fNext;
01020 LongestLine();
01021 return kTRUE;
01022 }
01023
01024
01025 Long_t TGText::GetLineLength(Long_t row)
01026 {
01027
01028
01029 if (!SetCurrentRow(row)) {
01030 return -1;
01031 }
01032 return (Long_t)fCurrent->GetLineLength();
01033 }
01034
01035
01036 Bool_t TGText::SetCurrentRow(Long_t row)
01037 {
01038
01039
01040
01041 Long_t count;
01042 if ((row < 0) || (row >= fRowCount)) {
01043 return kFALSE;
01044 }
01045 if (row > fCurrentRow) {
01046 for (count = fCurrentRow; count < row; count++) {
01047 if (!fCurrent->fNext) {
01048 fCurrentRow = count;
01049 return kFALSE;
01050 }
01051 fCurrent = fCurrent->fNext;
01052 }
01053 } else {
01054 if (fCurrentRow == row)
01055 return kTRUE;
01056 for (count = fCurrentRow; count > row; count--) {
01057 if (!fCurrent->fPrev) {
01058 fCurrentRow = count;
01059 return kFALSE;
01060 }
01061 fCurrent = fCurrent->fPrev;
01062 }
01063 }
01064 fCurrentRow = row;
01065 return kTRUE;
01066 }
01067
01068
01069 void TGText::ReTab(Long_t row)
01070 {
01071
01072
01073 if (!SetCurrentRow(row)) {
01074 return;
01075 }
01076
01077
01078 char *buffer;
01079 ULong_t i = 0;
01080
01081 buffer = fCurrent->fString;
01082 while (buffer[i] != '\0') {
01083 if (buffer[i] == '\t') {
01084 ULong_t j = i+1;
01085 while (buffer[j] == 16 && buffer[j] != '\0') {
01086 j++;
01087 }
01088 strcpy(buffer+i+1, buffer+j);
01089 }
01090 i++;
01091 }
01092
01093 char c, *src, *dst, *buf2;
01094 Long_t cnt;
01095
01096 buf2 = new char[kMaxLen+1];
01097 buf2[kMaxLen] = '\0';
01098 src = buffer;
01099 dst = buf2;
01100 cnt = 0;
01101 while ((c = *src++)) {
01102
01103 if (c == 0x09) {
01104 *dst++ = '\t';
01105 while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1)) {
01106 *dst++ = 16;
01107 }
01108 } else {
01109 *dst++ = c;
01110 }
01111 if (cnt++ >= kMaxLen-1) break;
01112 }
01113 *dst = '\0';
01114
01115 fCurrent->fString = buf2;
01116 fCurrent->fLength = strlen(buf2);
01117
01118 delete [] buffer;
01119 }
01120
01121
01122 Bool_t TGText::Search(TGLongPosition *foundPos, TGLongPosition start,
01123 const char *searchString,
01124 Bool_t direction, Bool_t caseSensitive)
01125 {
01126
01127
01128
01129
01130 if (!SetCurrentRow(start.fY))
01131 return kFALSE;
01132
01133 Ssiz_t x = kNPOS;
01134
01135 if (direction) {
01136 while(1) {
01137 TString s = fCurrent->fString;
01138 x = s.Index(searchString, (Ssiz_t)start.fX,
01139 caseSensitive ? TString::kExact : TString::kIgnoreCase);
01140 if (x != kNPOS) {
01141 foundPos->fX = x;
01142 foundPos->fY = fCurrentRow;
01143 return kTRUE;
01144 }
01145 if (!SetCurrentRow(fCurrentRow+1))
01146 break;
01147 start.fX = 0;
01148 }
01149 } else {
01150 while(1) {
01151 TString s = fCurrent->fString;
01152 for (int i = (int)start.fX; i >= 0; i--) {
01153 x = s.Index(searchString, (Ssiz_t)i,
01154 caseSensitive ? TString::kExact : TString::kIgnoreCase);
01155 if (x >= start.fX) {
01156 x = kNPOS;
01157 continue;
01158 }
01159 if (x != kNPOS) {
01160 break;
01161 }
01162 }
01163 if (x != kNPOS) {
01164 foundPos->fX = x;
01165 foundPos->fY = fCurrentRow;
01166 return kTRUE;
01167 }
01168 if (!SetCurrentRow(fCurrentRow-1)) {
01169 break;
01170 }
01171 start.fX = fCurrent->fLength;
01172 }
01173 }
01174 return kFALSE;
01175 }
01176
01177
01178 Bool_t TGText::Replace(TGLongPosition start, const char *oldText, const char *newText,
01179 Bool_t direction, Bool_t caseSensitive)
01180 {
01181
01182
01183 if (!SetCurrentRow(start.fY)) {
01184 return kFALSE;
01185 }
01186
01187 TGLongPosition foundPos;
01188 if (!Search(&foundPos, start, oldText, direction, caseSensitive)) {
01189 return kFALSE;
01190 }
01191
01192 TGLongPosition delEnd;
01193 delEnd.fY = foundPos.fY;
01194 delEnd.fX = foundPos.fX + strlen(oldText) - 1;
01195 DelText(foundPos, delEnd);
01196 InsText(foundPos, newText);
01197 return kTRUE;
01198 }
01199
01200
01201 void TGText::LongestLine()
01202 {
01203
01204
01205 Long_t line_count = 0;
01206 TGTextLine *travel = fFirst;
01207 fColCount = 0;
01208 while (travel) {
01209 if ((Long_t)travel->fLength > fColCount) {
01210 fColCount = travel->fLength;
01211 fLongestLine = line_count;
01212 }
01213 travel = travel->fNext;
01214 line_count++;
01215 }
01216 }
01217
01218
01219 TString TGText::AsString()
01220 {
01221
01222
01223 TString ret;
01224
01225 Long_t line_count = 0;
01226 TGTextLine *travel = fFirst;
01227 fColCount = 0;
01228
01229 while (travel) {
01230 if ((Long_t)travel->fLength > fColCount) {
01231 fColCount = travel->fLength;
01232 fLongestLine = line_count;
01233 }
01234 ret += travel->GetText();
01235 travel = travel->fNext;
01236 if (travel) ret += '\n';
01237 line_count++;
01238 }
01239
01240 return ret;
01241 }