#define TESTING /* * Overstrike and blank/tab manager * * This subroutine removes overstrikes from lines containing * or . It attempts to "do the right thing" for underlining and * overstriking. It also normalizes sequences, terminating * the previous line and returning the by itself in a record * containing only . * * Note that overstriking may be implemented either by or * . As long as there are no characters in * the line, either method will work properly. * * char * * overst(line, outbuf) * char *line; -- Text line to fix. * char *outbuf; -- Output buffer. * * On return, the line is copied to outbuf. overst() returns NULL * when the line has been exhausted. (This is needed for FORMFEED * processing.) * * The output buffer is always terminated by . Any * has been removed. * * If FORMFEED is not the first character on the line, the previous * line will have been terminated by NEWLINE. * * The input buffer is assumed to be terminated by . * All overstrike information is lost on . * * This module does not properly handle tabs and overstrikes that * span tab sequences. * * overst() is used in the following manner: * * char *linep; * * linep = NULL; -- initialize * for (;;) { -- read loop * if ((linep = fgets(inbuffer, sizeof inbuffer, infd)) == NULL) * break; -- exit if no more data * do { -- overst loop * linep = overst(linep, outbuffer); * if (linep != NULL || outbuffer[0] != EOS) * output(outbuffer); * } while (linep != NULL); * } * */ #define NULL (0) /* The null pointer */ #define EOS (0) /* End of string */ #define RETURN ('\r') /* */ #define NEWLINE ('\n') /* */ #define TAB ('\t') /* */ #define BACKSPACE ('\b') /* */ #define FORMFEED ('\f') /* */ #define BLANK (' ') /* space */ char * overst(inbuffer, outbuffer) char *inbuffer; /* Line to process */ char *outbuffer; /* Output buffer */ /* * Overstrike formatting routine. Returns NULL when line empty or * pointer to first byte in the partial output line. * * outbuffer must hold at least strlen(inbuffer) + 1 bytes. */ { register char c; /* Current character */ register char *ccpos; /* Buffer pointer */ register char *rmargin; /* Buffer end */ ccpos = rmargin = outbuffer; for (;;) { switch (c = *inbuffer++) { /* Look at next character */ case EOS: /* End of input string */ /* * The input line didn't end with (which happens if * the fgets() argument was shorter than the input record). * Terminate output buffer and return to caller. * Note that pending overstrikes are lost. */ *rmargin = EOS; return (NULL); case BACKSPACE: /* * Move printhead back */ if (ccpos > outbuffer) ccpos--; break; case TAB: /* * Tabs aren't handled correctly -- just put it * in the buffer. This doesn't work if you do * sequences of or followed * by tabs. */ *ccpos++ = TAB; if (ccpos > rmargin) rmargin = ccpos; break; case FORMFEED: if (rmargin > outbuffer) { /* * Terminate previous line and setup so we are recalled * with the FORMFEED at the start of the next line. */ *rmargin++ = NEWLINE; *rmargin = EOS; return (inbuffer - 1); /* Reget FORMFEED */ } /* * Formfeed at start of line. Output becomes * Continue with processing. */ *rmargin++ = FORMFEED; case NEWLINE: /* * Terminate the line, output, and reinitialize. */ *rmargin++ = NEWLINE; *rmargin = EOS; if (*inbuffer == EOS) /* If at end of input */ return (NULL); /* take normal exit. */ else /* Otherwise, there are */ return (inbuffer); /* multiple 's. */ case RETURN: /* * Return the carriage for overstriking. */ ccpos = outbuffer; break; default: /* * Plant the character unless underline or space overwrites * a "real" datum. Then move the printhead forward, * updating the right edge as needed. */ if (iscntrl(c)) /* If a control char */ break; /* just exit switch. */ else if (ccpos >= rmargin /* If at right margin */ || visibility(*ccpos) <= visibility(c)) *ccpos = c; /* Stuff the new char. */ ccpos++; /* Move the printhead */ if (ccpos > rmargin) /* and maybe update */ rmargin = ccpos; /* the right margin. */ break; /* Exit switch. */ } } } #include static int visibility(c) register int c; /* * Return our interest in seeing this character: * control/blank/tab == 0 -- tab might be a problem * punctuation == 1 * others == 2 */ { if (iscntrl(c) || isspace(c)) return (0); else if (ispunct(c)) return (1); else return (2); } #ifdef TESTING /* * Test program for overst() */ #include char inline[133]; char outline[133]; main() { register char *linep; linep = NULL; for (;;) { if ((linep = fgets(inline, sizeof inline, stdin)) == NULL) break; do { linep = overst(linep, outline); if (linep != NULL || outline[0] != EOS) fputs(outline, stdout); } while (linep != NULL); } } #endif