// ННГУ, ВМК, Курс "Методы программирования-2", С++, ООП
//
// ttext.cpp - Copyright (c) Гергель В.П. 04.09.2000? 19.01.2003
//
// Тексты - иерахическая структура представления

#define BufLength 80
#include <conio.h>
#include "ttext.h"

static char StrBuf[BufLength+1]; // буфер для ввода строк
static int  TextLevel;           // номер текущего уровня текста

TText :: TText(PTTextLink pl) {
  if ( pl == NULL ) pl = new TTextLink();
  pFirst = pl;
}

// навигация
int TText :: GoFirstLink ( void ) { // переход к первой строке
  while ( !Path.empty() ) Path.pop(); // очистка стека
  pCurrent = pFirst;
  if ( pCurrent == NULL ) SetRetCode(TextError); else SetRetCode(TextOK);
  return RetCode;
}

int TText :: GoDownLink  ( void ) { // переход к след. строке по Down
  SetRetCode(TextError);
  if ( pCurrent != NULL )
    if ( pCurrent->pDown != NULL ) {
      Path.push(pCurrent);
      pCurrent = pCurrent->pDown;
      SetRetCode(TextOK);
  }
  return RetCode;
}

int TText :: GoNextLink  ( void ) { // переход к след. строке по Next

Skipped...

}

int TText :: GoPrevLink  ( void ) { // переход к пред. позиции в тексте
  if ( Path.empty() ) SetRetCode(TextNoPrev);
  else {
    pCurrent = Path.top(); Path.pop();
    SetRetCode(TextOK);
  }
  return RetCode;
}

// доступ
string TText :: GetLine (void) { // чтение текущей строки
  if ( pCurrent == NULL ) return string("");
  else return string(pCurrent->Str);
}

void TText :: SetLine (string s) { // замена текущей строки
  if ( pCurrent == NULL ) SetRetCode(TextError);
  else strncpy(pCurrent->Str,s.c_str(),TextLineLength);
  pCurrent->Str[TextLineLength-1] = '\0';
}

// модификация
void TText :: InsDownLine (string s) { // вставка строки в подуровень
  if ( pCurrent == NULL ) SetRetCode(TextError);
  else {
    PTTextLink pd = pCurrent->pDown;
    PTTextLink pl = new TTextLink("",pd,NULL);
    strncpy(pl->Str,s.c_str(),TextLineLength);
    pl->Str[TextLineLength-1] = '\0'; // установка, если s длиннее Str
    pCurrent->pDown = pl;             // установка указателя на новую строку
    SetRetCode(TextOK);
  }
}

void TText :: InsDownSection(string s) { // вставка раздела в подуровень
  if ( pCurrent == NULL ) SetRetCode(TextError);
  else {
    PTTextLink pd = pCurrent->pDown;
    PTTextLink pl = new TTextLink("",NULL,pd);
    strncpy(pl->Str,s.c_str(),TextLineLength);
    pl->Str[TextLineLength-1] = '\0'; // установка, если s длиннее Str
    pCurrent->pDown = pl;             // установка указателя на новую строку
    SetRetCode(TextOK);
  }
}

void TText :: InsNextLine(string s) { // вставка строки в том же уровне

Skipped...

}

void TText :: InsNextSection(string s) { // вставка раздела в том же уровне

Skipped...

}

void TText :: DelDownLine(void) { // удаление строки в подуровне
  SetRetCode(TextOK);
  if ( pCurrent == NULL ) SetRetCode(TextError);
  else if ( pCurrent->pDown != NULL ) {
    PTTextLink pl1 = pCurrent->pDown;
    PTTextLink pl2 = pl1->pNext;
    if ( pl1->pDown == NULL ) pCurrent->pDown = pl2; // только для атома
  }
}

void TText :: DelDownSection(void) { // удаление раздела в подуровене
  SetRetCode(TextOK);
  if ( pCurrent == NULL ) SetRetCode(TextError);
  else if ( pCurrent->pDown != NULL ) {
    PTTextLink pl1  = pCurrent->pDown;
    PTTextLink pl2  = pl1->pNext;
    pCurrent->pDown = pl2;
  }
}

void TText :: DelNextLine(void) { // удаление строки в том же уровне

Skipped...

}

void TText :: DelNextSection(void) { // удаление раздела в том же уровне

Skipped...

}

// итератор
int TText :: Reset ( void ) { // установить на первую запись
  while ( !St.empty() ) St.pop(); // очистка стека
  // текущая строка в стеке не хранится
  // исключение - первая строка текста, которая на дне стека
  pCurrent = pFirst;
  if ( pCurrent != NULL ) {
    St.push(pCurrent);
    if ( pCurrent->pNext != NULL ) St.push(pCurrent->pNext);
    if ( pCurrent->pDown != NULL ) St.push(pCurrent->pDown);
  }
  return IsTextEnded();
}

int TText :: IsTextEnded ( void ) const { // таблица завершена ?
  return !St.size();
}

int TText :: GoNext ( void ) { // переход к следующей записи
  if ( !IsTextEnded() ) {
    pCurrent = St.top(); St.pop(); // если после выборки стек пуст, значит
    if ( pCurrent != pFirst ) {    // первая строка текста уже была обработана
      if ( pCurrent->pNext != NULL ) St.push(pCurrent->pNext);
      if ( pCurrent->pDown != NULL ) St.push(pCurrent->pDown);
    }
  }
  return IsTextEnded();
}

// копирование текста
PTTextLink TText :: GetFirstAtom(PTTextLink pl) { // поиск первого атома
  PTTextLink tmp = pl;
  while ( !tmp->IsAtom() ) {
    St.push(tmp); tmp = tmp->GetDown();
  }
  return tmp;
}

PTText TText :: GetCopy() { // копирование текста
  PTTextLink pl1, pl2, pl=pFirst, cpl=NULL;
  if ( pFirst != NULL ) {
    while ( !St.empty() ) St.pop(); // очистка стека
    while (1) {
      if ( pl != NULL ) {  // переход к первому атому
	pl = GetFirstAtom(pl); St.push(pl);
	pl = pl->GetDown();
      }
      else if ( St.empty() ) break;
      else {
        pl1 = St.top(); St.pop();
	if ( strstr(pl1->Str,"Copy") == NULL ) { // первый этап создания копии
          // создание копии - pDown на уже скопированный подуровень
	  pl2 = new TTextLink("Copy",pl1,cpl);   // pNext на оригинал

Skipped...

        }
        else { // второй этап создания копии

Skipped...

        }
      }
    }
  }
  return new TText(cpl);
}

// печать текста
void TText :: Print () {
  TextLevel = 0;
  PrintText(pFirst);
}

void TText :: PrintText ( PTTextLink ptl ) {
   if ( ptl != NULL ) {
     for ( int i=0; i< TextLevel; i++ ) cout << "  ";
     cout << " " << *ptl << endl;
     TextLevel++; PrintText(ptl->GetDown());
     TextLevel--; PrintText(ptl->GetNext());
  }
}

// чтение текста из файла
void TText :: Read ( char *pFileName ) {
  ifstream TxtFile(pFileName);
  TextLevel = 0;
  if ( TxtFile != NULL ) pFirst = ReadText(TxtFile);
}

PTTextLink TText :: ReadText (ifstream &TxtFile) {
  PTTextLink pHead, ptl;
  pHead = ptl = new TTextLink();
  while ( TxtFile.eof() == 0 ) {
    TxtFile.getline(StrBuf,BufLength,'\n');
    if ( StrBuf[0] == '}' ) { TextLevel--; break; }
    else if ( StrBuf[0] == '{' ) { // рекурсия
      TextLevel++; ptl->pDown = ReadText(TxtFile);
    }
    else {  // присоединение следующей строки
      ptl->pNext = new TTextLink(StrBuf,NULL,NULL);
      ptl = ptl->pNext;
    }
  }
  ptl = pHead;
  if ( pHead->pDown == NULL ) { // удаление первой строки, если нет подуровня
    pHead = pHead->pNext; delete ptl;
  }
  return pHead;
}
Хостинг от uCoz