[net.sources] Nroff filter for HP LaserJet printer wanted

wcs@ho95e.UUCP (x0705) (01/31/86)

In article <273@hlwpf.UUCP> barb@hlwpf.UUCP (B Amabile) writes:
>Does anyone have, know of, or is in the process of developing an nroff
>filter to drive the HP LaserJet printer???  We are currently using a
>filter with the UNIX lp software, but it doesn't allow us to "neatly"
>utilize the smarts that the printer has.

Here are two filter programs, one for the HP LaserJet, and an almost
identical one for the HP ThinkJet.  They're written in lex, but make
should understand them:
	lex hplj.l
	cc -O -ohplj lex.yy.c -ll
	rm lex.yy.c

Caveat - this won't do everything you want, at least for the LaserJet.
It's made to work with the A font cartridge, or any other cartridge
that has <generic fixed-space font>, <same-size bold-face font>, and
<same-size italic font>.  If you don't have those fonts available on
your LaserJet, it will do the best it can, but all the nice
right-justification that nroff did will be wasted if you have
proportional-space fonts.

Things it does right:
* It's in lex, so it's easy to change for other printers
* It will accept a wide variety of input formats, currently including
	HP escape sequences, TTY-37 escape sequences (i.e. stuff nroff
	likes to produce), Diablo/DASI escape sequences - but no
	graphics mode - just halfline, most combinations of letters,
	backspaces, and underlines in bizarre order.

Things that would be nice to add - please post if you do.
* user interface is boring - it's only a filter.  Add filename input -
	this means replacing the lex default main() with a real one.
* set up a front end so you can say hplj -Tprintertype
	if you want.
* handle diablo graphics mode.


: cut here-----
:  This is more or less a shar file.  Cut here and rn through /bin/sh.
:
sed 's/^://' >hplj.l <<EOF
:	/*****************************************************************/
:	/* hplj.l - Produce escape sequences for Boldface and Italics    */
:	/*	    on the HP LaserJet printer.  If your printer doesn't */
:	/*	    have Bold or Italic fonts it will default to boring. */
:	/* Acceptable input includes standard HP display sequences, and  */
:	/* the usual _\bX or X\bX\bX\bX sequences.  Support for          */
:	/* _______\b\b\b\b\b\b\bABCDEFG is also provided.                */
:	/*			Bill Stewart AT&T Bell Labs 3/21/85      */
:	/*                                                               */
:	/*   Syntax:    hplj <inputfile >outputfile                      */
:	/*                                                               */
:	/* If you modify this program, please add your comments here     */
:	/* and post the new version to net.sources if it's useful.       */
:	/*                                                               */
:	/*****************************************************************/
:			/*************************************************/
:			/* Note: Comments may be in funny places because */
:			/* of lex's rules about where you can put        */
:			/* executable statements and get them passed     */
:			/* through safely. Also, Blank lines are illegal */
:			/* and produce weird error msgs.		 */
:			/*************************************************/
:%Start	BOLD, ITALIC, DISPLAY
:	/* ROMAN_FONT start-state is state 0 */
:	/* Tokens for HP Display Sequences */
:END_DISPLAY	\033&d@
:START_UL	\033&dD
:START_DISPLAY	\033&d[^D@]
:	/* Backspaces and backarrows (LaserJet doesn't use ESCAPE-D */
:BS		(\b|\033D)
:	/*********************************/
:	/* Start program globals section */
:	/*********************************/
:%{
:#include <stdio.h>
:#define print(x) fputs(x,stdout)
:%}
:	char	*ROMAN_FONT ="\033(s0s0B";	/* Upright Medium Weight */
:	char	*BOLD_FONT  ="\033(s0s7B";	/* Upright Heavy  Weight */
:	char	*ITALIC_FONT="\033(s1s0B";	/* Italic  Medium Weight */
:	int	still_in = 0;
:						      /**/
:	/************************************************/
:	/* Rules section:	(after the %%)		*/
:	/*						*/
:	/*	<STATE>Patterns 	Actions  	*/
:	/*						*/
:	/************************************************/
:						      /**/
:	/************************************************/
:	/* Staying in BOLD or ITALIC			*/
:	/************************************************/
:%%
:<BOLD>[^_\r\n\b]{BS}	still_in=1;
:<ITALIC>_{BS}		still_in=1;
:<BOLD>_{BS}		{if (still_in<=0)	{BEGIN ITALIC;
:						print(ITALIC_FONT); still_in=1;}
:			else ECHO;}
:<ITALIC>[^_\b]{BS}	{if (still_in<=0)	{BEGIN BOLD;
:						print(BOLD_FONT); still_in=1;}
:			else {print(BOLD_FONT); print("_{BS}"); ECHO;} 	}
:<BOLD,ITALIC>[ \t]	ECHO;
:<BOLD,ITALIC>[\r\n]	{print(ROMAN_FONT); BEGIN 0; ECHO;}
:<BOLD,ITALIC>[^\r\n\t ]	{if (still_in-- <=0) {BEGIN 0; print(ROMAN_FONT);}
:			ECHO; /* echo whether you stayed in or not */ }
:{START_UL}		{
:	/************************************************/
:	/* Pass through HP Display modes like underline */
:	/************************************************/
:			BEGIN DISPLAY; still_in=0; print(ITALIC_FONT); }
:{START_DISPLAY}		{
:			BEGIN DISPLAY; still_in=0; print(BOLD_FONT); }
:<DISPLAY>{END_DISPLAY}	{
:			BEGIN 0      ; still_in=0; print(ROMAN_FONT); }
:<DISPLAY>[\r\n]		{BEGIN 0; print(ROMAN_FONT); ECHO;
:			/* On most HP's, return clears display mode */ }
:<DISPLAY>.		{ECHO;
:						      /**/
:	/************************************************/
:	/* Things to do in normal-text mode (state 0)	*/
:	/* (These have to be at the bottom so stuff     */
:	/* with non-zero start conditions gets done.    */
:	/************************************************/
:			}
:__+\b\b+	{/* Multi-character italic groups (REAL \b ONLY!!! ) */
:				/*  Count how many _'s you have   */
:		for (still_in=0; yytext[still_in]=='_'; still_in++) ;
:		if (still_in*2 > yyleng) REJECT; /* if more _ than \b, adjust */
:		still_in = yyleng - still_in;	/*  if more \b than _, adjust */
:		printf("%s%s", yytext, ITALIC_FONT);
:		BEGIN ITALIC;
:	/************************************************/
:	/* State 0 - Handle any remaining cursor motion */
:	/************************************************/
:		}
:\033D		print("\b");		/* HP left		*/
:\033A		print("\033&a-1R");	/* HP up		*/
:\033B		print("\033&a1R");	/* HP down		*/
:\033C		print("\033&a1C");	/* HP right		*/
:\0337		print("\033&a-1R");	/* TTY 37 up		*/
:\0338		print("\033=\033&a-1R");/* TTY 37 half-reverse	*/
:\0339		print("\033=");		/* TTY 37 half-linefeed	*/
:\033\n		print("\033&a-1R");	/* Diablo up		*/
:\033D		print("\033=\033&a-1R");/* Diablo half-reverse	*/
:\033U		{print("\033=");	/* Diablo half-linefeed	*/
:						      /**/
:	/************************************************/
:	/* State 0 - detect BOLD, ITALICs, and pass	*/
:	/* 	     regular text through.		*/
:	/************************************************/
:		}
:_{BS}		{BEGIN ITALIC; still_in=1; print(ITALIC_FONT);}
:[^\n]{BS}	{BEGIN BOLD;   still_in=1; print(BOLD_FONT);}
:\r$		; /* Eat trailing carriage returns */
:.		ECHO;
:\n		ECHO;
EOF
sed 's/^://' >hptj.l <<EOF
:	/*****************************************************************/
:	/* hptj.l - Produce escape sequences for Boldface and Italics    */
:	/*	    on the HP ThinkJet printer.                          */
:	/* Acceptable input includes standard HP display sequences, and  */
:	/* the usual _\bX or X\bX\bX\bX sequences.  Support for          */
:	/* _______\b\b\b\b\b\b\bABCDEFG is also provided.                */
:	/*			Bill Stewart AT&T Bell Labs 8/19/85      */
:	/*                                                               */
:	/*   Syntax:    hptj <inputfile >outputfile                      */
:	/*                                                               */
:	/* If you modify this program, please add your comments here     */
:	/* and post the new version to net.sources if it's useful.       */
:	/*****************************************************************/
:			/*************************************************/
:			/* Note: Comments may be in funny places because */
:			/* of lex's rules about where you can put        */
:			/* executable statements and get them passed     */
:			/* through safely. Also, Blank lines are illegal */
:			/* and produce weird error msgs.		 */
:			/*************************************************/
:%Start	BOLD, ITALIC, DISPLAY
:	/* ROMAN_FONT start-state is state 0 */
:	/* Tokens for HP Display Sequences */
:END_DISPLAY	\033&d@
:START_UL	\033&dD
:START_DISPLAY	\033&d[^D@]
:	/* Backspaces and backarrows (LaserJet doesn't use ESCAPE-D */
:BS		(\b|\033D)
:	/*********************************/
:	/* Start program globals section */
:	/*********************************/
:%{
:#include <stdio.h>
:#define print(x) fputs(x,stdout)
:%}
:	char	*ROMAN_FONT ="\033(s0B\033&d@";	/* Upright Medium Weight */
:	char	*BOLD_FONT  ="\033&d@\033(s1B";	/* Upright Heavy  Weight */
:	char	*ITALIC_FONT="\033(s0B\033&dD";	/* Italic  Medium Weight */
:	int	still_in = 0;
:						      /**/
:	/************************************************/
:	/* Rules section:	(after the %%)		*/
:	/*						*/
:	/*	<STATE>Patterns 	Actions  	*/
:	/*						*/
:	/************************************************/
:						      /**/
:	/************************************************/
:	/* Staying in BOLD or ITALIC			*/
:	/************************************************/
:%%
:<BOLD>[^_\r\n\b]{BS}	still_in=1;
:<ITALIC>_{BS}		still_in=1;
:<BOLD>_{BS}		{if (still_in<=0)	{BEGIN ITALIC;
:						print(ITALIC_FONT); still_in=1;}
:			else ECHO;}
:<ITALIC>[^_\b]{BS}	{if (still_in<=0)	{BEGIN BOLD;
:						print(BOLD_FONT); still_in=1;}
:			else {print(BOLD_FONT); print("_{BS}"); ECHO;} 	}
:<BOLD,ITALIC>[ \t]	ECHO;
:<BOLD,ITALIC>[\r\n]	{print(ROMAN_FONT); BEGIN 0; ECHO;}
:<BOLD,ITALIC>[^\r\n\t ]	{if (still_in-- <=0) {BEGIN 0; print(ROMAN_FONT);}
:			ECHO; /* echo whether you stayed in or not */ }
:{START_UL}		{
:	/************************************************/
:	/* Pass through HP Display modes like underline */
:	/************************************************/
:			BEGIN DISPLAY; still_in=0; print(ITALIC_FONT); }
:{START_DISPLAY}		{
:			BEGIN DISPLAY; still_in=0; print(BOLD_FONT); }
:<DISPLAY>{END_DISPLAY}	{
:			BEGIN 0      ; still_in=0; print(ROMAN_FONT); }
:<DISPLAY>[\r\n]		{BEGIN 0; print(ROMAN_FONT); ECHO;
:			/* On most HP's, return clears display mode */ }
:<DISPLAY>.		{ECHO;
:						      /**/
:	/************************************************/
:	/* Things to do in normal-text mode (state 0)	*/
:	/* (These have to be at the bottom so stuff     */
:	/* with non-zero start conditions gets done.    */
:	/************************************************/
:			}
:__+\b\b+	{/* Multi-character italic groups (REAL \b ONLY!!! ) */
:				/*  Count how many _'s you have   */
:		for (still_in=0; yytext[still_in]=='_'; still_in++) ;
:		if (still_in*2 > yyleng) REJECT; /* if more _ than \b, adjust */
:		still_in = yyleng - still_in;	/*  if more \b than _, adjust */
:		printf("%s%s", yytext, ITALIC_FONT);
:		BEGIN ITALIC;
:	/************************************************/
:	/* State 0 - Handle any remaining cursor motion */
:	/************************************************/
:		}
:\033D		print("\b");		/* HP left		*/
:\033A		print("\033&a-1R");	/* HP up		*/
:\033B		print("\033&a1R");	/* HP down		*/
:\033C		print("\033&a1C");	/* HP right		*/
:\0337		print("\033&a-1R");	/* TTY 37 up		*/
:\0338		print("\033=\033&a-1R");/* TTY 37 half-reverse	*/
:\0339		print("\033=");		/* TTY 37 half-linefeed	*/
:\033\n		print("\033&a-1R");	/* Diablo up		*/
:\033D		print("\033=\033&a-1R");/* Diablo half-reverse	*/
:\033U		{print("\033=");	/* Diablo half-linefeed	*/
:						      /**/
:	/************************************************/
:	/* State 0 - detect BOLD, ITALICs, and pass	*/
:	/* 	     regular text through.		*/
:	/************************************************/
:		}
:_{BS}		{BEGIN ITALIC; still_in=1; print(ITALIC_FONT);}
:[^\n]{BS}	{BEGIN BOLD;   still_in=1; print(BOLD_FONT);}
:\r$		; /* Eat trailing carriage returns */
:.		ECHO;
:\n		ECHO;
EOF
-- 
# Bill Stewart, AT&T Bell Labs 2G-202, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs