/*  parseline.c  -- (part of efr)  Copyright © 1989 by William F. Hammond  */
/*               --  breaks a string into LineParts                        */
#ifndef TDM_H
#include "tdm.h"
#endif
/*********************************************************************/
struct LinePart *parseline(lpstr, lpp)
UBYTE *lpstr;
struct LinePart *lpp;             /*  address of previous LinePart        */
{
struct LinePart *lp, *lpn;        /*  lp points to the LinePart herein    */
                                  /*      allocated; it is the return     */
                                  /*  lpn points to the successor of lp   */
register USHORT i;
SHORT lastclear, lpl, controlcount;
int isl;
UBYTE *nstr;                       /*  for recursive call to self          */
USHORT clearcount, lnctlseq, ctladj;
UBYTE drawflag, fontflag;
if(lpstr == NULL) return NULL;
if(strlen(lpstr) == 0) return NULL; 
lp = (struct LinePart *)AllocMem(LPSZ, MEMF_CLEAR);
if (lp == NULL)
   {
   fputs("parseline: Insufficient memory for LinePart\xa", stderr);
   if(lpp != NULL)
      {
      lp = lpp;
      while (lp)
         {
         lpn = lp->lp_Prev;
         FreeMem(lp, LPSZ);
         lp = lpn;
         }
      }
   return NULL;
   }
lp->lp_Address = (ULONG)lpstr;
lp->lp_Length = NULB;
lp->lp_Move = NULB;
lp->lp_FontStyle = NULB;
lp->lp_DrawStyle = NULB;
lp->lp_Next = (struct LinePart *)NULL;
lp->lp_Prev = lpp;
lp->lp_Trans = 0L;
/*  Examine the characters in lpstr;  */
isl = strlen(lpstr);
if(lpstr[isl-1] == '\n')
   {
   lpstr[isl-1] = '\0';
   isl --;
   }
lastclear = -1;
i = 0;
/******************    controlcount is the offset to lpstr for lp->lp_Address
 *  lnctlseq detects the controlcount contribution of the current character
 *  clearcount is the number of clear characters including accessory controls
 *  ctladj is the number of accessory controls
 *  clearcount and ctladj are used to set lp->lp_Length  *******************/
clearcount = 0; controlcount = 0; lnctlseq = 0, ctladj = 0;
drawflag = NULB; fontflag = NULB;
while (i < isl)
   {
   switch (lpstr[i])
      {
      case 0x08:
         {
         lnctlseq = 1;
         if(lastclear <0)
            {
            lp->lp_Trans -- ;
            controlcount += lnctlseq;
            ctladj += (lnctlseq -1); 
            }
         break;
         }
      case 0x09:
         {
         lnctlseq = 1;
         if(lastclear <0)
            {
            lp->lp_Trans += 3;
            controlcount += lnctlseq;
            ctladj += (lnctlseq -1); 
            }
         break;
         }
      case 0x1B:
         {
         if((lpstr[i+1] == '[') && (lpstr[i+3] == 'm'))
            {
            switch (lpstr[i+2])
               {
               case '0':      /*  plain font style and drawing style  */
                  {
                  lnctlseq = 4;
                  if(lastclear <0)
                     {
                     fontflag = 1;
                     lp->lp_FontStyle = FS_NORMAL;
                     drawflag = 1;
                     lp->lp_DrawStyle = JAMX;
                     controlcount += lnctlseq;
                     ctladj += (lnctlseq -1); 
                     }
                  break;
                  }
               case '1':      /*  boldface font style                 */
                  {
                  lnctlseq = 4;
                  if(lastclear <0)
                     {
                     fontflag = 1;
                     lp->lp_FontStyle = lp->lp_FontStyle | FSF_BOLD;
                     controlcount += lnctlseq;
                     ctladj += (lnctlseq -1); 
                     }
                  break;
                  }
               case '3':      /*  italic font style                   */
                  {
                  lnctlseq = 4;
                  if(lastclear <0)
                     {
                     fontflag = 1;
                     lp->lp_FontStyle = lp->lp_FontStyle | FSF_ITALIC;
                     controlcount += lnctlseq;
                     ctladj += (lnctlseq -1); 
                     }
                  break;
                  }
               case '4':      /*  underlined font style                */
                  {
                  lnctlseq = 4;
                  if(lastclear <0)
                     {
                     fontflag = 1;
                     lp->lp_FontStyle = lp->lp_FontStyle | FSF_UNDERLINED;
                     controlcount += lnctlseq;
                     ctladj += (lnctlseq -1); 
                     }
                  break;
                  }
               case '7':      /*  inverse video drawing style         */
                  {
                  lnctlseq = 4;
                  if(lastclear <0)
                     {
                     drawflag = 1;
                     lp->lp_DrawStyle = (JAMX|INVERSVID);
                     controlcount += lnctlseq;
                     ctladj += (lnctlseq -1); 
                     }
                  break;
                  }
               default:
                  {
                  lnctlseq = 0; lastclear = i;  clearcount ++;  break;
                  }
               }
            }
         else
            {
            lnctlseq = 0; lastclear = i;  clearcount ++;  break;
            }
         break;
         }
      case 0x86:                                         /*  move down  */
      case 0x88:
         {
         lnctlseq = 1;
         if(lastclear <0)
            {
            lp->lp_Move = lp->lp_Move + 1;
            controlcount += lnctlseq;
            ctladj += (lnctlseq -1); 
            }
         break;
         }
      case 0x87:                                         /*  move up    */
      case 0x8A:
         {
         lnctlseq = 1;
         if(lastclear <0)
            {
            lp->lp_Move = lp->lp_Move - 1;
            controlcount += lnctlseq;
            ctladj += (lnctlseq -1); 
            }
         break;
         }
      default:
         {
         lnctlseq = 0; lastclear = i;  clearcount ++;  break;
         }
      }        /***  switch end  ***/
   if( (lnctlseq) && (lastclear >= 0) ) break;
   i ++;    
   }         /***  loop (i < strlen(lpstr))  ***/
lpl = lastclear + 1;     /*  offset of first char. in next LinePart  */
lp->lp_Address = (ULONG)lpstr + (ULONG)controlcount;
if(controlcount > 0) clearcount = clearcount - ctladj;
lp->lp_Length = (UBYTE)(clearcount);
if(drawflag) lp->lp_DrawStyle ++;
if(fontflag) lp->lp_FontStyle ++;
if (lpl < isl)
   {
   if (lastclear >=0)
      {                /*  At least one more LinePart required      */
      nstr = &lpstr[lpl];
      lp->lp_Next = parseline(nstr, lp);
      }
   else        /*  Nothing but control chars in lpstr, thus lpl = 0    */
      {
      lp->lp_Length = NULB;     /*  Signals "control changes only"  */
      }
   }
return lp;
}
