home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
txtutl
/
ovrsgr.arc
/
OVRSGR.C
next >
Wrap
C/C++ Source or Header
|
1986-11-06
|
21KB
|
1,018 lines
/*********************************************************************
Name: ovrsgr.c
Version: 1.0
COPYRIGHT (c) 1985 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD MASS.
ALL RIGHTS RESERVED.
Permission to copy without fee all or part of this material is granted
provided that copies are not made or distributed for direct commercial
advantage, the Digital Equipment Corporation copyright notice appears,
the disclaimer below appears, and notice is given that copying is by
permission of Digital Equipment Corporation. To copy otherwise
requires a specific license.
DISCLAIMER:
The information herein is subject to change without notice and should
not be construed as a commitment by Digital Equipment Corporation.
Digital Equipment Corporation assumes no responsibility for the use or
reliability of this software. This software is provided "as is,"
without any warranty of any kind, express or implied. Digital
Equipment Corporation will not be liable in any event for any damages
including any loss of data, profit, or savings, claims against the
user by any other party, or any other incidental or consequential
damages arising out of the use of, or inability to use, this software,
even if Digital Equipment Corporation is advised of the possibility of
such damage.
DEFECT REPORTING AND SUGGESTIONS:
Please send reports of defects or suggestions for improvement directly
to the author:
Brian Hetrick
Digital Equipment Corporation
110 Spit Brook Road ZKO1-2/J10
Nashua NH 03062-2698
Do NOT file a Software Performance Report on this software, call the
Telephone Support Center regarding this software, contact your Digital
Field Office regarding this software, or use any other mechanism
provided for Digital's supported and warranted software.
FACILITY:
General utility programs.
ABSTRACT:
Converts a file encoded in eight-bit ASCII with limited control
character use into an equivalent file using the "set graphic
rendition" escape sequences to indicate bolding and underlining.
Applicable ANSI standards are X3.4 (7-bit ASCII), X3.64 (Addition-
al controls for use with ASCII), and (proposed) X3.4.2 (8-bit
ASCII).
ENVIRONMENT:
CP/M-86/80, compiled with Mark Williams Co. MWC86.
MS-DOS, compiled with Computer Innovations Co. C86.
VAX/VMS, compiled with VAX C.
AUTHOR: Brian Hetrick, CREATION DATE: 10 May 1985.
MODIFIED BY:
Brian Hetrick, 10-May-85: Version 1.0
000 - Original creation of module.
1986/11/06 -- Rahul Dhesi -- For ANSI.SYS on Iclones: (a) changed
blob to be rectangular graphics character; (b) changed underlining
to be inverse video. See "#ifdef ICLONE".
*********************************************************************/
/*
* INCLUDE FILES:
*/
#include <stdio.h>
/*
* TABLE OF CONTENTS:
*/
/*
* MACROS:
*/
#define MAXLINLEN 512 /* Maximum width of line */
#define FLG_SPAN 1 /* Span whitespace */
#define ATR_BLOB 1 /* Different char overprint*/
#define ATR_UNDR 2 /* Underline overprint */
#define ATR_BOLD 4 /* Same char overprint */
/*
* The following character is device dependent. It should print as
* a blob of some type. It is used to indicate that several dissim-
* ilar characters have been overprinted. The sequence given invokes
* the G1 character set, prints a lowercase 'a', and returns to the
* G0 character set. On devices such as Digital's VT1xx and VT2xx
* terminals, where the G1 set has been set to the "special graphics"
* character set, this prints a checkerboard pattern. The SCS (set
* character set) escape sequence to put the special graphics char-
* acter set into G1 is <ESC>)0.
*/
#ifdef ICLONE
#define CHR_BLOB "\xFE" /* small rectangle */
#else
#define CHR_BLOB "\016a\017" /* Checkerboard */
#endif
/*
* OWN STORAGE:
*/
struct chr_pos
{
char cp_attr;
char cp_char;
};
static FILE
* outfile;
static int
flags,
hpos = 0,
indent;
static struct chr_pos
line_image [MAXLINLEN];
/*
* EXTERNAL REFERENCES:
*/
static change_attr (old_attr, new_attr)
int
old_attr,
new_attr;
/*********************************************************************
FUNCTIONAL DESCRIPTION:
Minimally updates "set graphic rendition" attributes.
The term "minimal" is used advisedly. The VT100 series and clones
allow only clearing all attributes and setting particular attri-
butes, while the VT200 series additionally allows clearing partic-
ular attributes. Also, the VT100 series and clones allow only the
7-bit ASCII representation of CSI. For maximal device independ-
ence, the VT100 limitations are assumed.
FORMAL PARAMETERS:
Old_attribute.rg.v - The set of graphic rendition attributes cur-
rently in effect.
New_attributes.rg.v - The set of graphic rendition attributes to
be put into effect.
RETURN VALUE:
None.
IMPLICIT INPUTS:
outfile - The file to which the escape sequence is to be sent.
IMPLICIT OUTPUTS:
None.
SIDE EFFECTS:
Sends an escape sequence to the output file.
*********************************************************************/
{
int
first_code;
if (old_attr != new_attr)
{
/*
* Have to do something. Start the escape sequence.
*/
putc ('\033', outfile);
putc ('[', outfile);
/*
* See if must reset attributes.
*/
if (old_attr & (~ new_attr))
{
putc ('0', outfile);
first_code = 0;
old_attr = 0;
}
else
{
first_code = 1;
}
/*
* Need only attributes to be added.
*/
new_attr &= ~ old_attr;
/*
* Do the attributes.
*/
if (new_attr & ATR_BOLD)
{
if (! first_code)
{
putc (';', outfile);
}
putc ('1', outfile);
first_code = 0;
}
if (new_attr & ATR_UNDR)
{
if (! first_code)
{
putc (';', outfile);
}
#ifdef ICLONE
putc ('7', outfile);
#else
putc ('4', outfile);
#endif
}
/*
* End the escape sequence.
*/
putc ('m', outfile);
}
}
static outlin (eol)
char
eol;
/*********************************************************************
FUNCTIONAL DESCRIPTION:
Creates a text line corresponding to the line_image array.
FORMAL PARAMETERS:
eol.rc.v - The vertical movement character that ended the line.
RETURN VALUE:
None.
IMPLICIT INPUTS:
line_image - A description of the line to be created.
outfile - The pointer to the stream upon which the line is to be
created.
IMPLICIT OUTPUTS:
None.
SIDE EFFECTS:
Produces output upon outfile.
*********************************************************************/
{
int
column,
last_attr,
span_attr;
struct chr_pos
* end_ptr,
* max_ptr,
* start_ptr;
/*
* Turn NULs into spaces and find line length.
*/
for (start_ptr = & line_image [0], max_ptr = & line_image [-1];
start_ptr < & line_image [MAXLINLEN];
start_ptr ++)
{
if (0 == start_ptr -> cp_char)
{
start_ptr -> cp_char = ' ';
if (0 != start_ptr -> cp_attr)
{
max_ptr = start_ptr;
}
}
else
{
/*
* It is not a space.
*/
max_ptr = start_ptr;
}
}
last_attr = 0;
if (max_ptr != & line_image [-1])
{
/*
* If necessary, make attributes span blanks. Do this by
* finding characters surrounding spans of blanks, and ORing
* the blank's attributes with the AND of the attributes of
* the surrounding characters.
*
* In the following, start_pos is the index of the first
* blank to treat, and start_ptr points at its line_image[]
* entry; end_pos is the index of the first character not to
* treat, and end_ptr points at its line_image[] entry. Note
* that any initial blanks are NOT to be treated.
*/
if (flags & FLG_SPAN)
{
start_ptr = & line_image [-1];
span_attr = 0;
while (start_ptr <= max_ptr)
{
/*
* Find first non-blank character following start_
* ptr.
*/
end_ptr = start_ptr + 1;
while ((end_ptr <= max_ptr) &&
(' ' == end_ptr -> cp_char))
{
end_ptr ++;
}
if (end_ptr > max_ptr)
{
/*
* There is no first non-blank character fol-
* lowing start_ptr.
*/
break;
}
/*
* Find attributes to span.
*/
span_attr &= end_ptr -> cp_attr;
if (0 != span_attr)
{
/*
* Span them.
*/
while (start_ptr < end_ptr)
{
(start_ptr ++) -> cp_attr |= span_attr;
}
}
/*
* Advance to next space, and retain attribute of im-
* mediately previous character.
*/
span_attr = end_ptr -> cp_attr;
start_ptr = end_ptr + 1;
while ((start_ptr <= max_ptr) &&
(' ' != start_ptr -> cp_char))
{
span_attr = ((start_ptr ++) -> cp_attr) &
(~ ATR_BLOB);
}
}
}
/*
* Finally, put out the line.
*/
for (column = 0; column < indent; column ++)
{
putc (' ', outfile);
}
start_ptr = & line_image [0];
while (start_ptr <= max_ptr)
{
if (start_ptr -> cp_attr != last_attr)
{
change_attr (last_attr, start_ptr -> cp_attr);
last_attr = start_ptr -> cp_attr;
}
/*
* Put out a character.
*/
if (start_ptr -> cp_attr & ATR_BLOB)
{
fputs (CHR_BLOB, outfile);
}
else
{
putc (start_ptr -> cp_char, outfile);
}
start_ptr ++;
}
}
/*
* Reset attributes.
*/
if (last_attr != 0)
{
change_attr (last_attr, 0);
}
/*
* Put out end of line.
*/
if ((max_ptr != & line_image [-1]) && (eol != '\n') &&
(eol != '\205'))
{
putc ('\r', outfile);
}
if (eol != '\0')
{
putc (eol, outfile);
}
}
static int inlin (infile, eol)
FILE
* infile;
char
* eol;
/*********************************************************************
FUNCTIONAL DESCRIPTION:
Creates a line_image array corresponding to a text line.
The end of the line is assumed to coincide with a control char-
acter causing vertical motion. These control characters are
LF/NL, VT, FF, IND, NEL, PLD, PLU, and RI. Note that LF/NL is as-
sumed to be NL, which returns the active position to the first
character on a line, while VT and FF are assumed not to do so.
ANSI X3.4 permits either behavior with any or all of these char-
acters. Also, the 7-bit representations of IND, NEL, PLD, PLU,
and RI are not recognized.
FORMAL PARAMETERS:
infile.mr.r - The stream from which a line is to be retrieved.
eol.wc.r - The vertical movement character that ended the line.
NUL if the line was terminated by end of file.
RETURN VALUE:
0 - A line was successfully retrieved. line_image has the image
of the line retrieved.
EOF - End of file was encountered. line_image does not have the
image of a line.
IMPLICIT INPUTS:
hpos - horizontal position in line as of entry.
IMPLICIT OUTPUTS:
hpos - horizontal position in line as of exit.
line_image - A description of the line that was read.
SIDE EFFECTS:
Consumes input from infile.
*********************************************************************/
{
static char
/*
* Map of what characters cause special horizontal motion.
*
* BS 0x08, 8, 0010
* HT 0x09, 9, 0011
* CR 0x0D, 13, 0015
* SP 0x20, 32, 0040
* NEL 0x85, 133, 0205
* NBSP 0xA0, 160, 0240
*
* Of the characters above, NEL alone also causes vertical
* motion.
*/
hm_map [] =
{0x00, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
/*
* Map of what characters cause vertical motion.
*
* LF 0x0A, 10, 0012 (also known as NL)
* VT 0x0B, 11, 0013
* FF 0x0C, 12, 0014
* IND 0x84, 132, 0204
* NEL 0x85, 133, 0205
* PLD 0x8B, 139, 0213
* PLU 0x8C, 140, 0214
* RI 0x8D, 141, 0215
*
* Note that NEL alone of the above causes horizontal motion.
* But with "text" I/O in C, LF is NL, and so implies hori-
* zontal motion.
*/
vm_map [] =
{0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
/*
* Map of bit encodings used in the above tables.
*/
bit_mask [] =
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int
in_char,
in_pos;
struct chr_pos
* in_ptr;
/*
* Check for end of file.
*/
if (feof (infile))
{
return (EOF);
}
/*
* Initialize the line image.
*/
if (hpos == 0)
{
for (in_ptr = & line_image [0];
in_ptr < & line_image [MAXLINLEN];
in_ptr ++)
{
in_ptr -> cp_attr = 0;
in_ptr -> cp_char = 0;
}
}
/*
* Get the line.
*/
in_ptr = & line_image [hpos];
while (EOF != (in_char = getc (infile)))
{
/*
* Check if the character is a line terminator.
*/
if (vm_map [in_char >> 3] & bit_mask [in_char & 7])
{
/*
* Check for LF and NEL.
*/
if (('\n' == in_char) || ('\205' == in_char))
{
/*
* Yes. Effect return to margin.
*/
in_ptr = & line_image [0];
}
break;
}
/*
* Check for special horizontal motion.
*/
if (hm_map [in_char >> 3] & bit_mask [in_char & 7])
{
/*
* Yes. Do what depends on character. Cases are given
* hopefully in most efficient order. NBSP has same
* action as SP, but SP occurs far more frequently.
*/
switch (in_char)
{
case '\040': /* Space. */
in_ptr ++;
if (in_ptr >= & line_image [MAXLINLEN])
{
in_ptr --;
}
break;
case '\011': /* Horizontal tab. */
in_pos = in_ptr - & line_image [0];
in_pos &= ~ 7;
in_pos += 8;
if (in_pos >= MAXLINLEN)
{
in_pos = MAXLINLEN - 1;
}
in_ptr = & line_image [in_pos];
break;
case '\015': /* Carriage return. */
in_ptr = & line_image [0];
break;
case '\010': /* Backspace. */
in_ptr --;
if (in_ptr < & line_image [0])
{
in_ptr = & line_image [0];
}
break;
default: /* Non-break space. */
in_ptr ++;
if (in_ptr >= & line_image [MAXLINLEN])
{
in_ptr --;
}
break;
}
}
else
{
/*
* No special horizontal motion. Check for control char-
* acter.
*/
if ((in_char & 0x60) && (in_char != 0x7F))
{
/*
* Is not 0x00 to 0x1F or 0x80 to 0x9F or 0x7F. Is
* a graphic character. But handle underline spec-
* ially.
*/
if ('_' == in_char)
{
/*
* Mark underline as underscoring.
*/
in_ptr -> cp_attr |= ATR_UNDR;
}
else if (0 == in_ptr -> cp_char)
{
/*
* Not already a character at this position.
*/
in_ptr -> cp_char = in_char;
}
else if (in_char == in_ptr -> cp_char)
{
/*
* Already same character at this position.
*/
in_ptr -> cp_attr |= ATR_BOLD;
}
else
{
/*
* Multiple overstrikes.
*/
in_ptr -> cp_attr |= ATR_BLOB;
}
in_ptr ++;
}
}
}
/*
* Remember horizontal position.
*/
hpos = in_ptr - & line_image [0];
/*
* Return the line terminator.
*/
if (EOF == in_char)
{
* eol = '\0';
}
else
{
* eol = in_char;
}
return 0;
}
static dofile (infile)
FILE
* infile;
/*********************************************************************
FUNCTIONAL DESCRIPTION:
Processes all lines of an input file.
FORMAL PARAMETERS:
Input_file.mr.r - The stream from which input is taken.
RETURN VALUE:
None.
IMPLICIT INPUTS:
hpos - If 0, the line just read may be printed.
IMPLICIT OUTPUTS:
None.
SIDE EFFECTS:
Consumes input from the input file, and produces output on the
output file.
*********************************************************************/
{
char
eol;
while (EOF != inlin (infile, & eol))
{
if (hpos == 0)
{
outlin (eol);
}
}
}
int main (argc, argv)
int
argc;
char
* argv [];
/*********************************************************************
FUNCTIONAL DESCRIPTION:
Main program for overstrike to SGR translator.
Parses the command line. The command line is of the form:
ovrsgr [-i indent] [-o outfile] [-s] infile [...]
where:
ovrsgr is the name of the program.
-i indicates that the following token is a decimal integer that is
the number of characters by which the print image is to be
shifted right.
-o indicates that the following token is the name of a file to
which output is to be sent.
-s indicates that bold and underline are to "span" whitespace, so
that phrases may be underlined as a whole.
infile is the name of an input file. Several such names may be
given; if so, the files are processed as if they were concat-
enated into a single file.
If no input files are given, input is taken from the standard in-
put. If no output file is given, output is sent to the standard
output.
FORMAL PARAMETERS:
Argument_count.rg.v - A count of the number of elements of Argu-
ment_vector that are valid.
Argument_vector.rt.ra - The individual tokens of the command line.
RETURN VALUE:
None. Program termination is always via exit. Exit codes on VMS
are:
1 - All okay.
4 - Could not open output file.
Exit codes on other than VMS are:
0 - All okay.
1 - Could not open output file.
IMPLICIT INPUTS:
hpos - If non-zero, the last line must be printed.
stdin - A pointer to the standard input stream.
stdout - A pointer to the standard output stream.
stderr - A pointer to the standard error stream.
IMPLICIT OUTPUTS:
flags - A vector of flags indicating processing options.
indent - A count of the number of spaces to prepend to the print
image.
outfile - The pointer to the stream to which output is to be sent.
SIDE EFFECTS:
Reads the input files. Writes the output file.
*********************************************************************/
{
char
* argp,
* outname;
FILE
* infile;
int
argch,
argi;
/*
* Parse flags.
*/
outname = (char *) NULL;
flags = 0;
indent = 0;
for (argi = 1; argi < argc; argi ++)
{
argp = argv [argi];
if ('-' != * argp ++)
{
break;
}
while ('\0' != (argch = * argp ++))
{
switch (argch)
{
case 'i':
/*
* Indent amount.
*/
indent = atoi (argv [++ argi]);
break;
case 'o':
/*
* Output file name.
*/
outname = argv [++ argi];
break;
case 's':
/*
* Span white space.
*/
flags |= FLG_SPAN;
break;
default:
/*
* Unknown.
*/
fputs ("Unknown flag: ", stderr);
putc (argch, stderr);
fputs (", ignored\n", stderr);
break;
}
}
}
/*
* Get output file.
*/
if ((char *) NULL != outname)
{
#ifdef vms
if ((FILE *) NULL == (outfile =
fdopen (creat (outname, 0644, "rat=cr", "rfm=var", "mrs=0"), "w")))
#else
if ((FILE *) NULL == (outfile = fopen (outname, "w")))
#endif
{
fputs ("Cannot open file ", stderr);
fputs (outname, stderr);
fputs (", aborting\n", stderr);
#ifdef vms
exit (2);
#else
exit (1);
#endif
}
}
else
{
outfile = stdout;
}
/*
* Do input files.
*/
if (argi == argc)
{
dofile (stdin);
}
else
{
for ( ; argi < argc; argi ++)
{
if ((FILE *) NULL == (infile = fopen (argv [argi], "r")))
{
fputs ("Cannot open file ", stderr);
fputs (argv [argi], stderr);
fputs (", continuing\n", stderr);
}
else
{
dofile (infile);
fclose (infile);
}
}
}
if (hpos != 0)
{
outlin ('\n');
}
#ifdef vms
exit (1);
#else
exit (0);
#endif
}