//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  ------------------------------------------------------------------
//  This library 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.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  Text -> Paragraph conversion.
//  ------------------------------------------------------------------

#include <gstrall.h>
#include <gtxtpara.h>


//  ------------------------------------------------------------------

int GParagraph::ConvertText(char* _tptr, uint _tlen) {

  // Text position counter
  uint _tpos = 0;

  // Main conversion loop
  while(_tpos < _tlen) {

    // Skip SOFTCR, NUL and LF characters at the start of a paragraph
    while(_tpos < _tlen) {
      switch(*_tptr) {
        case SOFTCR:
          if(softcr != LF)  break;  // Allow soft-cr to be a real char
        case NUL: case LF:
          _tptr++;  _tpos++;  continue;
      }
      break;
    }

    // Break out of loop at end of text
    if(_tpos >= _tlen)
      break;

    // Paragraph start pointer and position
    char* _pptr = _tptr;
    uint _ppos = _tpos;

    // Find next CR or end of text
    while((*_tptr != CR) and (_tpos < _tlen))
      _tptr++, _tpos++;

    // NUL-terminate paragraph (overwriting the CR if any)
    *_tptr = NUL;

    // Add paragraph
    AddParagraph(_pptr, _tpos-_ppos);
  }

  return lines;
}


//  ------------------------------------------------------------------

uint GParagraph::CheckCtrlLines() {

  // Non-ctrl text size including a terminating CR
  uint _length = 0;

  if(paraidx) {

    // Flags
    int _got_tearline = false;
    int _got_origin = false;

    // Point to one item past the last item
    GParaData* _pdptr = &paraidx[lines];
    int _line = lines;

    // Check paragraphs in bottom-up order
    do {

      // Previous paragraph
      _line--;
      _pdptr--;

      // Shortcut alias
      char* _ptr = _pdptr->text;

      // Switch the CHR4 value
      switch(*(dword*)_ptr) {

        // AREA: echo identifier
        case CHR4_AREA:
          // Mark all occurrences. Check in a separate loop afterwards
          if(strneql(_ptr, "AREA:", 5))
            _pdptr->control = CTRL_AREA;
          break;

        // --- Tearline
        case CHR4_TEARLINENUL:
        case CHR4_TEARLINESPACE:
          // Only the last tearline is valid
          if(not _got_tearline)
            if(strneql(_ptr, "---\0", 4) or strneql(_ptr, "--- ", 4))
              _pdptr->control = CTRL_TEARLINE, _got_tearline = true;
          break;

        // * Origin:
        case CHR4_ORIGIN:
          // Only the last origin is valid and only if before any tearline
          if(not _got_tearline and not _got_origin)
            if(strneql(_ptr, " * Origin: ", 11))
              _pdptr->control = CTRL_ORIGIN, _got_origin = true;
          break;

        // SEEN-BY: (non-kludge version)
        case CHR4_SEENBY:
          // Non-kludge version is only valid after tearline/origin
          if(not _got_tearline and not _got_origin)
            if(strneql(_ptr, "SEEN-BY: ", 9))
              _pdptr->control = CTRL_SEENBY;
          break;

        // Standard known kludges
        case CHR4_INTL:     if(strneql(_ptr, "\001INTL ", 6))       _pdptr->control = CTRL_INTL;     break;
        case CHR4_FMPT:     if(strneql(_ptr, "\001FMPT ", 6))       _pdptr->control = CTRL_FMPT;     break;
        case CHR4_TOPT:     if(strneql(_ptr, "\001TOPT ", 6))       _pdptr->control = CTRL_TOPT;     break;
        case CHR4_MSGID:    if(strneql(_ptr, "\001MSGID: ", 8))     _pdptr->control = CTRL_MSGID;    break;
        case CHR4_REPLY:    if(strneql(_ptr, "\001REPLY: ", 8))     _pdptr->control = CTRL_REPLY;    break;
        case CHR4_PID:      if(strneql(_ptr, "\001PID: ", 6))       _pdptr->control = CTRL_PID;      break;
        case CHR4_SEENBY1:  if(strneql(_ptr, "\001SEEN-BY: ", 10))  _pdptr->control = CTRL_SEENBY1;  break;
        case CHR4_PATH:     if(strneql(_ptr, "\001PATH: ", 7))      _pdptr->control = CTRL_PATH;     break;
        case CHR4_CHARSET:  if(strneql(_ptr, "\001CHARSET: ", 10))  _pdptr->control = CTRL_CHARSET;  break;
        case CHR4_CHRS:     if(strneql(_ptr, "\001CHRS: ", 7))      _pdptr->control = CTRL_CHRS;     break;
        case CHR4_TZUTC:    if(strneql(_ptr, "\001TZUTC: ", 8))     _pdptr->control = CTRL_TZUTC;    break;
        case CHR4_VIA:      if(strneql(_ptr, "\001Via ", 5))        _pdptr->control = CTRL_VIA;      break;
        case CHR4_FLAGS:    if(strneql(_ptr, "\001FLAGS ", 7))      _pdptr->control = CTRL_FLAGS;    break;
      }

      // Mark unknown kludges
      if(not _pdptr->control and (*_ptr == CTRL_A))
        _pdptr->control = CTRL_UNKNOWNKLUDGE;

      // Calculate non-ctrl text size
      if(_pdptr->control < CTRL_KLUDGE)
        _length += _pdptr->length + 1;

    } while(_line);

    // Flags
    int _got_area = false;
    int _got_nonctrl = false;

    // Loop to check AREA: occurrences
    while(_line < lines) {

      // Is this a control line?
      if(_pdptr->control) {

        // Eliminate AREA: duplicates and any occurrence after first non-ctrl line
        if(_pdptr->control == CTRL_AREA) {
          if(_got_area or _got_nonctrl)
            _pdptr->control = 0;
          _got_area = true;
        }
      }
      else {

        // Flag first occurrence of a non-ctrl line
        _got_nonctrl = true;
      }

      // Next paragraph
      _pdptr++;
      _line++;
    }
  }

  // Return total non-ctrl text size
  return _length;
}


//  ------------------------------------------------------------------