/* 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; }