// @(#)root/gui:$Name: $:$Id: TGText.cxx,v 1.14 2004/05/24 11:45:08 brun Exp $
// Author: Fons Rademakers 26/04/98
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
This source is based on Xclass95, a Win95-looking GUI toolkit.
Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
Xclass95 is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
**************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TGText //
// //
// A TGText is a multi line text buffer. It allows the text to be //
// loaded from file, saved to file and edited. It is used in the //
// TGTextEdit widget. Single line text is handled by TGTextBuffer //
// and the TGTextEntry widget. //
// //
//////////////////////////////////////////////////////////////////////////
#include "TGText.h"
const Int_t kMaxLen = 8000;
ClassImp(TGTextLine)
//______________________________________________________________________________
TGTextLine::TGTextLine()
{
// Create empty line of text (default ctor).
fLength = 0;
fString = 0;
fPrev = fNext = 0;
}
//______________________________________________________________________________
TGTextLine::TGTextLine(TGTextLine *line)
{
// Initialize line of text with other line of text (not copy ctor).
fLength = line->GetLineLength();
fString = 0;
if (fLength > 0)
fString = line->GetText(0, line->GetLineLength());
fPrev = fNext = 0;
}
//______________________________________________________________________________
TGTextLine::TGTextLine(const char *string)
{
// Initialize line of text with a const char*.
if (string) {
fLength = strlen(string);
fString = new char[fLength+1];
strcpy(fString, string);
} else {
fLength = 0;
fString = 0;
}
fPrev = fNext = 0;
}
//______________________________________________________________________________
TGTextLine::~TGTextLine()
{
// Delete a line of text.
if (fString)
delete [] fString;
}
//______________________________________________________________________________
void TGTextLine::Clear()
{
// Clear a line of text.
if (fString)
delete [] fString;
fString = 0;
fLength = 0;
}
//______________________________________________________________________________
void TGTextLine::DelText(ULong_t pos, ULong_t length)
{
// Delete length chars from line starting at position pos.
if (fLength == 0 || pos >= fLength)
return;
if (pos+length > fLength)
length = fLength - pos;
if (fLength - length <= 0) {
delete [] fString;
fLength = 0;
fString = 0;
return;
}
char *newstring = new char[fLength - length+1];
strncpy(newstring, fString, (UInt_t)pos);
strncpy(newstring+pos, fString+pos+length, UInt_t(fLength-pos-length));
delete [] fString;
fString = newstring;
fLength = fLength - length;
fString[fLength] = '\0';
}
//______________________________________________________________________________
void TGTextLine::InsText(ULong_t pos, const char *text)
{
// Insert text in line starting at position pos.
if (pos > fLength || !text)
return;
char *newstring = new char[strlen(text)+fLength+1];
if (fString != 0)
strncpy(newstring, fString, (UInt_t)pos);
strcpy(newstring+pos, text);
if (fLength - pos > 0)
strncpy(newstring+pos+strlen(text), fString+pos, UInt_t(fLength-pos));
fLength = fLength + strlen(text);
delete [] fString;
fString = newstring;
fString[fLength] ='\0';
}
//______________________________________________________________________________
char *TGTextLine::GetText(ULong_t pos, ULong_t length)
{
// Get length characters from line starting at pos. Returns 0
// in case pos and length are out of range. The returned string
// must be freed by the user.
if (pos >= fLength)
return 0;
if (pos + length > fLength)
length = fLength - pos;
char *retstring = new char[length+1];
retstring[length] = '\0';
strncpy(retstring, fString+pos, (UInt_t)length);
return retstring;
}
//______________________________________________________________________________
void TGTextLine::DelChar(ULong_t pos)
{
// Delete a character from the line.
char *newstring;
if ((fLength <= 0) || (pos > fLength))
return;
newstring = new char[fLength];
strncpy(newstring, fString, (UInt_t)pos-1);
if (pos < fLength)
strncpy(newstring+pos-1, fString+pos, UInt_t(fLength-pos+1));
else
newstring[pos-1] = 0;
delete [] fString;
fString = newstring;
fLength--;
}
//______________________________________________________________________________
void TGTextLine::InsChar(ULong_t pos, char character)
{
// Insert a character at the specified position.
char *newstring;
if (pos > fLength)
return;
newstring = new char[fLength+2];
newstring[fLength+1] = '\0';
if (fLength > 0)
strncpy (newstring, fString, (UInt_t)pos);
newstring[pos] = character;
if (fLength - pos > 0)
strncpy(newstring+pos+1, fString+pos, UInt_t(fLength-pos));
delete [] fString;
fString = newstring;
fLength++;
}
//______________________________________________________________________________
char TGTextLine::GetChar(ULong_t pos)
{
// Get a character at the specified position from the line.
// Returns -1 if pos is out of range.
if ((fLength <= 0) || (pos >= fLength))
return -1;
return fString[pos];
}
ClassImp(TGText)
//______________________________________________________________________________
void TGText::Init()
{
// Common initialization method.
fFirst = new TGTextLine;
fCurrent = fFirst;
fCurrentRow = 0;
fColCount = 0;
fRowCount = 1;
fLongestLine = 0;
fIsSaved = kTRUE;
}
//______________________________________________________________________________
TGText::TGText()
{
// Create default (empty) text buffer.
Init();
}
//______________________________________________________________________________
TGText::TGText(TGText *text)
{
// Create text buffer and initialize with other text buffer.
TGLongPosition pos, end;
pos.fX = pos.fY = 0;
end.fY = text->RowCount() - 1;
end.fX = text->GetLineLength(end.fY) - 1;
Init();
InsText(pos, text, pos, end);
}
//______________________________________________________________________________
TGText::TGText(const char *string)
{
// Create text buffer and initialize with single line string.
TGLongPosition pos;
pos.fX = pos.fY = 0;
Init();
InsText(pos, string);
}
//______________________________________________________________________________
TGText::~TGText()
{
// Destroy text buffer.
Clear();
delete fFirst;
}
//______________________________________________________________________________
void TGText::Clear()
{
// Clear text buffer.
TGTextLine *travel = fFirst->fNext;
TGTextLine *toDelete;
while (travel != 0) {
toDelete = travel;
travel = travel->fNext;
delete toDelete;
}
fFirst->Clear();
fFirst->fNext = 0;
fCurrent = fFirst;
fCurrentRow = 0;
fColCount = 0;
fRowCount = 1;
fLongestLine = 0;
fIsSaved = kTRUE;
fFilename = "";
}
//______________________________________________________________________________
Bool_t TGText::Load(const char *fn, Long_t startpos, Long_t length)
{
// Load text from file fn. Startpos is the begin from where to
// load the file and length is the number of characters to read
// from the file.
Bool_t isFirst = kTRUE;
Bool_t finished = kFALSE;
Long_t count, charcount, i, cnt;
FILE *fp;
char buf[kMaxLen], c, *src, *dst, *buffer, *buf2;
TGTextLine *travel, *temp;
travel = fFirst;
if (!(fp = fopen(fn, "r"))) return kFALSE;
i = 0;
fseek(fp, startpos, SEEK_SET);
charcount = 0;
while (fgets(buf, kMaxLen, fp)) {
if ((length != -1) && (charcount+(Int_t)strlen(buf) > length)) {
count = length - charcount;
finished = kTRUE;
} else
count = kMaxLen;
charcount += strlen(buf);
buf2 = new char[count+1];
buf2[count] = '\0';
src = buf;
dst = buf2;
cnt = 0;
while ((c = *src++)) {
// Don't put CR or NL in buffer
if (c == 0x0D || c == 0x0A)
break;
// Expand tabs
else if (c == 0x09) {
*dst++ = '\t';
while (((dst-buf2) & 0x7) && (cnt++ < count-1))
*dst++ = 16; //*dst++ = ' ';
} else
*dst++ = c;
if (cnt++ >= count-1) break;
}
*dst = '\0';
temp = new TGTextLine;
buffer = new char[strlen(buf2)+1];
strcpy(buffer, buf2);
temp->fLength = strlen(buf2);
temp->fString = buffer;
temp->fNext = temp->fPrev = 0;
if (isFirst) {
delete fFirst;
fFirst = temp;
fCurrent = temp;
travel = fFirst;
isFirst = kFALSE;
} else {
travel->fNext = temp;
temp->fPrev = travel;
travel = travel->fNext;
}
++i;
delete [] buf2;
if (finished)
break;
}
fclose(fp);
// Remember the number of lines
fRowCount = i;
if (fRowCount == 0)
fRowCount++;
fIsSaved = kTRUE;
fFilename = fn;
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::LoadBuffer(const char *txtbuf)
{
// Load a 0 terminated buffer. Lines will be split at '\n'.
Bool_t isFirst = kTRUE;
Bool_t finished = kFALSE, lastnl = kFALSE;
Long_t i, cnt;
TGTextLine *travel, *temp;
char buf[kMaxLen], c, *src, *dst, *buffer, *buf2, *s;
const char *tbuf = txtbuf;
travel = fFirst;
if (!tbuf || !strlen(tbuf))
return kFALSE;
i = 0;
next:
if ((s = (char*)strchr(tbuf, '\n'))) {
if (s-tbuf+1 >= kMaxLen-1) {
strncpy(buf, tbuf, kMaxLen-2);
buf[kMaxLen-2] = '\n';
buf[kMaxLen-1] = 0;
} else {
strncpy(buf, tbuf, s-tbuf+1);
buf[s-tbuf+1] = 0;
}
tbuf = s+1;
} else {
if ((Int_t)strlen(tbuf) >= kMaxLen) {
strncpy(buf, tbuf, kMaxLen-1);
buf[kMaxLen-1] = 0;
} else
strcpy(buf, tbuf);
finished = kTRUE;
}
buf2 = new char[kMaxLen+1];
buf2[kMaxLen] = '\0';
src = buf;
dst = buf2;
cnt = 0;
while ((c = *src++)) {
// Don't put CR or NL in buffer
if (c == 0x0D || c == 0x0A)
break;
// Expand tabs
else if (c == 0x09) {
*dst++ = '\t';
while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1))
*dst++ = 16; //*dst++ = ' ';
} else
*dst++ = c;
if (cnt++ >= kMaxLen-1) break;
}
*dst = '\0';
temp = new TGTextLine;
buffer = new char[strlen(buf2)+1];
strcpy(buffer, buf2);
temp->fLength = strlen(buf2);
temp->fString = buffer;
temp->fNext = temp->fPrev = 0;
if (isFirst) {
delete fFirst;
fFirst = temp;
fCurrent = temp;
travel = fFirst;
isFirst = kFALSE;
} else {
travel->fNext = temp;
temp->fPrev = travel;
travel = travel->fNext;
}
++i;
delete [] buf2;
// make sure that \n generates a single empty line in the TGText
if (!lastnl && !*tbuf && *(tbuf-1) == '\n') {
tbuf--;
lastnl = kTRUE;
}
if (!finished && tbuf && strlen(tbuf))
goto next;
// Remember the number of lines
fRowCount = i;
if (fRowCount == 0)
fRowCount++;
fIsSaved = kTRUE;
fFilename = "";
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::Save(const char *fn)
{
// Save text buffer to file fn.
char *buffer;
TGTextLine *travel = fFirst;
FILE *fp;
if (!(fp = fopen(fn, "w"))) return kFALSE;
while (travel) {
ULong_t i = 0;
buffer = new char[travel->fLength+2];
strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
buffer[travel->fLength] = '\n';
buffer[travel->fLength+1] = '\0';
while (buffer[i] != '\0') {
if (buffer[i] == '\t') {
ULong_t j = i+1;
while (buffer[j] == 16 && buffer[j] != '\0')
j++;
strcpy(buffer+i+1, buffer+j);
}
i++;
}
if (fputs(buffer, fp) == EOF) {
delete [] buffer;
fclose(fp);
return kFALSE;
}
delete [] buffer;
travel = travel->fNext;
}
fIsSaved = kTRUE;
fFilename = fn;
fclose(fp);
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::Append(const char *fn)
{
// Append buffer to file fn.
char *buffer;
TGTextLine *travel = fFirst;
FILE *fp;
if (!(fp = fopen(fn, "a"))) return kFALSE;
while (travel) {
ULong_t i = 0;
buffer = new char[travel->fLength+2];
strncpy(buffer, travel->fString, (UInt_t)travel->fLength);
buffer[travel->fLength] = '\n';
buffer[travel->fLength+1] = '\0';
while (buffer[i] != '\0') {
if (buffer[i] == '\t') {
ULong_t j = i+1;
while (buffer[j] == 16 && buffer[j] != '\0')
j++;
strcpy(buffer+i+1, buffer+j);
}
i++;
}
if (fputs(buffer, fp) == EOF) {
delete [] buffer;
fclose(fp);
return kFALSE;
}
delete [] buffer;
travel = travel->fNext;
}
fIsSaved = kTRUE;
fclose(fp);
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::DelChar(TGLongPosition pos)
{
// Delete character at specified position pos.
if ((pos.fY >= fRowCount) || (pos.fY < 0))
return kFALSE;
if (!SetCurrentRow(pos.fY)) return kFALSE;
fCurrent->DelChar(pos.fX);
fIsSaved = kFALSE;
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::InsChar(TGLongPosition pos, char c)
{
// Insert character c at the specified position pos.
if ((pos.fY >= fRowCount) || (pos.fY < 0) || (pos.fX < 0))
return kFALSE;
if (!SetCurrentRow(pos.fY)) return kFALSE;
fCurrent->InsChar(pos.fX, c);
fIsSaved = kFALSE;
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
char TGText::GetChar(TGLongPosition pos)
{
// Get character a position pos. If charcater not valid return -1.
if (pos.fY >= fRowCount)
return -1;
if (!SetCurrentRow(pos.fY)) return -1;
return fCurrent->GetChar(pos.fX);
}
//______________________________________________________________________________
Bool_t TGText::DelText(TGLongPosition start, TGLongPosition end)
{
// Delete text between start and end positions. Returns false in
// case of failure (start and end not being within bounds).
if ((start.fY < 0) || (start.fY >= fRowCount) ||
(end.fY < 0) || (end.fY >= fRowCount))
return kFALSE;
if ((end.fX < 0) || (end.fX > GetLineLength(end.fY)))
return kFALSE;
char *tempbuffer;
if (!SetCurrentRow(start.fY)) return kFALSE;
if (start.fY == end.fY) {
fCurrent->DelText(start.fX, end.fX-start.fX+1);
return kTRUE;
}
fCurrent->DelText(start.fX, fCurrent->fLength-start.fX);
SetCurrentRow(fCurrentRow+1);
for (long i = start.fY+1; i < end.fY; i++)
DelLine(fCurrentRow);
tempbuffer = fCurrent->GetText(end.fX+1, fCurrent->fLength-end.fX-1);
DelLine(fCurrentRow);
SetCurrentRow(start.fY);
if (tempbuffer)
fCurrent->InsText(fCurrent->GetLineLength(), tempbuffer);
else {
if (fCurrent->fNext) {
fCurrent->InsText(fCurrent->fLength, fCurrent->fNext->fString);
DelLine(fCurrentRow+1);
SetCurrentRow(start.fY);
}
}
fIsSaved = kFALSE;
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::InsText(TGLongPosition ins_pos, TGText *src,
TGLongPosition start_src, TGLongPosition end_src)
{
// Insert src text from start_src to end_src into text at position ins_pos.
// Returns false in case of failure (start_src, end_src out of range for
// src, and ins_pos out of range for this).
/*
if ((start_src.fY < 0) || (start_src.fY >= src->RowCount()) ||
(end_src.fY < 0) || (end_src.fY >= src->RowCount()))
return kFALSE;
if ((start_src.fX < 0) || (start_src.fX > src->GetLineLength(start_src.fY)) ||
(end_src.fX < 0) || (end_src.fX > src->GetLineLength(end_src.fY)))
return kFALSE;
if ((ins_pos.fY < 0) || (ins_pos.fY > fRowCount))
return kFALSE;
if ((ins_pos.fX < 0) || (ins_pos.fX > GetLineLength(ins_pos.fY)))
return kFALSE;
*/
if (ins_pos.fY > fRowCount)
return kFALSE;
TGLongPosition pos;
ULong_t len;
char *lineString;
char *restString;
TGTextLine *following;
if (ins_pos.fY == fRowCount) { // for appending text
pos.fY = fRowCount - 1;
pos.fX = GetLineLength(pos.fY);
BreakLine(pos); // current row is set by this
} else {
// otherwise going to the desired row
if (!SetCurrentRow(ins_pos.fY)) return kFALSE;
}
// preparing first line to be inserted
restString = fCurrent->GetText(ins_pos.fX, fCurrent->fLength - ins_pos.fX);
fCurrent->DelText(ins_pos.fX, fCurrent->fLength - ins_pos.fX);
following = fCurrent->fNext;
// inserting first line
if (start_src.fY == end_src.fY)
len = end_src.fX - start_src.fX+1;
else
len = src->GetLineLength(start_src.fY) - start_src.fX;
if (len > 0) {
lineString = src->GetLine(start_src, len);
fCurrent->InsText(ins_pos.fX, lineString);
delete [] lineString;
}
// [...] inserting possible lines
pos.fY = start_src.fY+1;
pos.fX = 0;
for ( ; pos.fY < end_src.fY; pos.fY++) {
lineString = src->GetLine(pos, src->GetLineLength(pos.fY));
fCurrent->fNext = new TGTextLine(lineString);
fCurrent->fNext->fPrev = fCurrent;
fCurrent = fCurrent->fNext;
fRowCount++;
fCurrentRow++;
delete [] lineString;
}
// last line of inserted text is as special as first line
if (start_src.fY != end_src.fY) {
pos.fY = end_src.fY;
pos.fX = 0;
lineString = src->GetLine(pos, end_src.fX+1);
fCurrent->fNext = new TGTextLine(lineString);
fCurrent->fNext->fPrev = fCurrent;
fCurrent = fCurrent->fNext;
fRowCount++;
fCurrentRow++;
delete [] lineString;
}
// ok, now we have to add the rest of the first destination line
if (restString) {
#if 0
if (ins_pos.fX == 0) {
fCurrent->fNext = new TGTextLine(restString);
fCurrent->fNext->fPrev = fCurrent;
fCurrent = fCurrent->fNext;
fRowCount++;
fCurrentRow++;
} else
#endif
fCurrent->InsText(fCurrent->fLength, restString);
delete [] restString;
}
// now re-linking the rest of the origin text
fCurrent->fNext = following;
if (fCurrent->fNext)
fCurrent->fNext->fPrev = fCurrent;
LongestLine();
fIsSaved = kFALSE;
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::InsText(TGLongPosition pos, const char *buffer)
{
// Insert single line at specified position. Return false in case position
// is out of bounds.
if (pos.fY < 0 || pos.fY > fRowCount)
return kFALSE;
if (pos.fY == fRowCount) {
SetCurrentRow(fRowCount-1);
fCurrent->fNext = new TGTextLine(buffer);
fCurrent->fNext->fPrev = fCurrent;
fRowCount++;
} else {
SetCurrentRow(pos.fY);
fCurrent->InsText(pos.fX, buffer);
}
LongestLine();
fIsSaved = kFALSE;
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::AddText(TGText *text)
{
// Add another text buffer to this buffer.
TGLongPosition end, start_src, end_src;
end.fY = fRowCount;
end.fX = 0;
start_src.fX = start_src.fY = 0;
end_src.fY = text->RowCount()-1;
end_src.fX = text->GetLineLength(end_src.fY)-1;
fIsSaved = kFALSE;
return InsText(end, text, start_src, end_src);
}
//______________________________________________________________________________
Bool_t TGText::InsLine(ULong_t pos, const char *string)
{
// Insert string before specified position.
// Returns false if insertion failed.
TGTextLine *previous, *newline;
if ((Long_t)pos > fRowCount)
return kFALSE;
if ((Long_t)pos < fRowCount)
SetCurrentRow(pos);
else
SetCurrentRow(fRowCount-1);
if (!fCurrent) return kFALSE;
previous = fCurrent->fPrev;
newline = new TGTextLine(string);
newline->fPrev = previous;
if (previous)
previous->fNext = newline;
else
fFirst = newline;
newline->fNext = fCurrent;
fCurrent->fPrev = newline;
fRowCount++;
fCurrentRow++;
LongestLine();
fIsSaved = kFALSE;
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGText::DelLine(ULong_t pos)
{
// Delete specified row. Returns false if row does not exist.
if (!SetCurrentRow(pos) || (fRowCount == 1))
return kFALSE;
TGTextLine *travel = fCurrent;
if (travel == fFirst) {
fFirst = fFirst->fNext;
fFirst->fPrev = 0;
} else {
travel->fPrev->fNext = travel->fNext;
if (travel->fNext) {
travel->fNext->fPrev = travel->fPrev;
fCurrent = fCurrent->fNext;
} else {
fCurrent = fCurrent->fPrev;
fCurrentRow--;
}
}
delete travel;
fRowCount--;
fIsSaved = kFALSE;
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
char *TGText::GetLine(TGLongPosition pos, ULong_t length)
{
// Return string at position pos. Returns 0 in case pos is not valid.
// The returned string must be deleted by the user.
if (SetCurrentRow(pos.fY))
return fCurrent->GetText(pos.fX, length);
return 0;
}
//______________________________________________________________________________
Bool_t TGText::BreakLine(TGLongPosition pos)
{
// Break line at position pos. Returns false if pos is not valid.
if (!SetCurrentRow(pos.fY))
return kFALSE;
if ((pos.fX < 0) || (pos.fX > (Long_t)fCurrent->fLength))
return kFALSE;
TGTextLine *temp;
char *tempbuffer;
if (pos.fX < (Long_t)fCurrent->fLength) {
tempbuffer = fCurrent->GetText(pos.fX, fCurrent->fLength-pos.fX);
temp = new TGTextLine(tempbuffer);
fCurrent->DelText(pos.fX, fCurrent->fLength - pos.fX);
delete [] tempbuffer;
} else
temp = new TGTextLine;
temp->fPrev = fCurrent;
temp->fNext = fCurrent->fNext;
fCurrent->fNext = temp;
if (temp->fNext)
temp->fNext->fPrev = temp;
fIsSaved = kFALSE;
fRowCount++;
fCurrentRow++;
fCurrent = fCurrent->fNext;
LongestLine();
return kTRUE;
}
//______________________________________________________________________________
Long_t TGText::GetLineLength(Long_t row)
{
// Get length of specified line. Returns -1 if row does not exist.
if (!SetCurrentRow(row))
return -1;
return (Long_t)fCurrent->GetLineLength();
}
//______________________________________________________________________________
Bool_t TGText::SetCurrentRow(Long_t row)
{
// Make specified row the current row. Returns false if row does not exist.
// In which case fCurrent is not changed or set to the last valid line.
Long_t count;
if ((row < 0) || (row >= fRowCount))
return kFALSE;
if (row > fCurrentRow) {
for (count = fCurrentRow; count < row; count++) {
if (!fCurrent->fNext) {
fCurrentRow = count;
return kFALSE;
}
fCurrent = fCurrent->fNext;
}
} else {
if (fCurrentRow == row)
return kTRUE;
for (count = fCurrentRow; count > row; count--) {
if (!fCurrent->fPrev) {
fCurrentRow = count;
return kFALSE;
}
fCurrent = fCurrent->fPrev;
}
}
fCurrentRow = row;
return kTRUE;
}
//______________________________________________________________________________
void TGText::ReTab(Long_t row)
{
// Redo all tabs in a line. Needed after a new tab is inserted.
if (!SetCurrentRow(row))
return;
// first remove all special tab characters (16)
char *buffer;
ULong_t i = 0;
buffer = fCurrent->fString;
while (buffer[i] != '\0') {
if (buffer[i] == '\t') {
ULong_t j = i+1;
while (buffer[j] == 16 && buffer[j] != '\0')
j++;
strcpy(buffer+i+1, buffer+j);
}
i++;
}
char c, *src, *dst, *buf2;
Long_t cnt;
buf2 = new char[kMaxLen+1];
buf2[kMaxLen] = '\0';
src = buffer;
dst = buf2;
cnt = 0;
while ((c = *src++)) {
// Expand tabs
if (c == 0x09) {
*dst++ = '\t';
while (((dst-buf2) & 0x7) && (cnt++ < kMaxLen-1))
*dst++ = 16;
} else
*dst++ = c;
if (cnt++ >= kMaxLen-1) break;
}
*dst = '\0';
fCurrent->fString = buf2;
fCurrent->fLength = strlen(buf2);
delete [] buffer;
}
//______________________________________________________________________________
Bool_t TGText::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) or backward direction. Returns true if
// found and foundPos is set accordingly.
if (!SetCurrentRow(start.fY))
return kFALSE;
Ssiz_t x = kNPOS;
if (direction) {
while(1) {
TString s = fCurrent->fString;
x = s.Index(searchString, (Ssiz_t)start.fX,
caseSensitive ? TString::kExact : TString::kIgnoreCase);
if (x != kNPOS) {
foundPos->fX = x;
foundPos->fY = fCurrentRow;
return kTRUE;
}
if (!SetCurrentRow(fCurrentRow+1))
break;
start.fX = 0;
}
} else {
while(1) {
TString s = fCurrent->fString;
for (int i = (int)start.fX; i >= 0; i--) {
x = s.Index(searchString, (Ssiz_t)i,
caseSensitive ? TString::kExact : TString::kIgnoreCase);
if (x >= start.fX) {
x = kNPOS;
continue;
}
if (x != kNPOS)
break;
}
if (x != kNPOS) {
foundPos->fX = x;
foundPos->fY = fCurrentRow;
return kTRUE;
}
if (!SetCurrentRow(fCurrentRow-1))
break;
start.fX = fCurrent->fLength;
}
}
return kFALSE;
}
//______________________________________________________________________________
Bool_t TGText::Replace(TGLongPosition start, const char *oldText, const char *newText,
Bool_t direction, Bool_t caseSensitive)
{
// Replace oldText by newText. Returns false if nothing replaced.
if (!SetCurrentRow(start.fY))
return kFALSE;
TGLongPosition foundPos;
if (!Search(&foundPos, start, oldText, direction, caseSensitive))
return kFALSE;
TGLongPosition delEnd;
delEnd.fY = foundPos.fY;
delEnd.fX = foundPos.fX + strlen(oldText) - 1;
DelText(foundPos, delEnd);
InsText(foundPos, newText);
return kTRUE;
}
//______________________________________________________________________________
void TGText::LongestLine()
{
// Set fLongestLine.
Long_t line_count = 0;
TGTextLine *travel = fFirst;
fColCount = 0;
while (travel) {
if ((Long_t)travel->fLength > fColCount) {
fColCount = travel->fLength;
fLongestLine = line_count;
}
travel = travel->fNext;
line_count++;
}
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.