home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
man2rtf.zoo
/
man2rtf
/
Man2RTF.c
Wrap
C/C++ Source or Header
|
1990-10-14
|
22KB
|
774 lines
/*
Copyright 1990 by Norman Graham, Brandywine Softworks.
Permission to use, copy, modify, and distribte this software for
any purpose and without fee is hereby granted, provided that the
above copyright notice appear in all copies and that both the
copyright notice and this permission notice and warranty disclaimer
appear in supporting documentation, and that the name of Brandywine
Softworks or Norman Graham not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
Brandywine Softworks and Norman Graham disclaim all warranties with
regard to this software, including all implied warranties of
merchantability and fitness. In no event shall Brandywine Softworks
or Norman Graham be liable for any special, indirect, or consequential
damages or any damages whatsoever resulting from loss of use, data,
or profits, whether in an action of contract, negligence, or other
tortious action, arising out of or in connection with the use or
performance of this software.
*/
/******************************************************************************
File: Man2RTF.c
Author: Norman Graham
Date: 2 September 1990
Usage: Man2RTF [-f|-h8|-h7] <Man.file >RTF.File
Description:
Man2RTF is a quick hack to convert a text file to Rich Text Format.
It converts some of the control sequences common in Un*x files into
the equivalent RTF character formatting. It converts the following
sequences:
"a\ba" => Bold 'a'
"a\ba\ba" => Bold 'a'
"a\ba\ba\ba" => Bold 'a'
"_\ba" => Underlined 'a'
"_\ba\ba" => Underlined Bold 'a'
"`" => Typographer's Opening Single Quote
"'" => Typographer's Closing Single Quote
Any other string with a '\b' in it is written to stderr as an error.
The idea is that Man2RTF will tell you when you need to extend it
to handle control sequences not currently handled.
Any non-control sequence is just copied to the RTF file.
Options:
-f Format the text with 10 point Courier and format the page
to display 66 lines on a vertical 8.5 inch by 11 inch page.
Margins are Top = 0.45 inch, Bottom = 0.45 inch, and
Left = 1.25 inches.
-h8 Format the text with 8 point Courier and format the page
to display two columns of 66 lines on a horizontal 8.5 inch
by 11 inch page. Margins are Top = 0.21 inch, Bottom = 0.21 inch,
Left = 0.15 inch, and Right = 0.15 inch with 0.15 inch between
columns. This format is not as useful as '-h7'.
-h7 Format the text with 7 point Courier and format the page
to display two columns of 66 lines on a horizontal 8.5 inch
by 11 inch page. Margins are Top = 0.9 inch, Bottom = 0.45 inch,
Left = 0.45 inch, and Right = 0.45 inch with 0.8 inch between
columns. This is a nice format because it provides a top margin
for binding and the space between columns is large enough that
you need not worry about the columns running together.
If no option is specified, Man2RTF will only generate font style
information; it will not generate font name, font size, or
page formating information.
Caveats:
If you use this tool on a Un*x box with the intention of
downloading the resulting file to your Mac, you need to
be aware that the resulting file probably contains typographer's
opening and closing quotes. These characters have values > 127
(i.e. their high bits are set), thus you'll need to make special
arangements to download the file. I'd suggest using mcvert
(available on sumex-aim) to convert the file to a macbinary
text file and then do a macbinary file transfer. As an alternative,
you could just nullify the typographer quote code by changing
kOpenSingleQuote to '`' and kCloseSingleQuote to '\''.
MPW build commands:
In MPW, you can build Man2RTF by executing the following commands
directly from this file. You'll need to edit the Link command
to put the tool where you want it and to repair the line continuation
characters that undoubtly will be munged by transport over the
internet.
C "{Active}"
Link -w -c 'MPS ' -t MPST 6
"{Active}".o 6
"{CLibraries}"StdClib.o 6
"{CLibraries}"CInterface.o 6
"{Libraries}"Stubs.o 6
"{CLibraries}"CRuntime.o 6
"{Libraries}"Interface.o 6
-o {MPW}Tools:LocalTools:Man2RTF
Delete "{Active}".o
Porting:
This program is written in ANSI C. If your compiler does not
support the ANSI C standard, you will need to modify this code.
Pay attention to the function prototypes, the new style function
definitions, and the string concatenation [used in calls to fprintf()
and puts()]. I believe most C compilers now support enum types,
but if yours doesn't you'll need to do some modifications here
as well.
For MPW users. Watch out for munged characters in the Link
command (from above) and in the definitions of kOpenSingleQuote
and kCloseSingleQuote. These definitions contain characters
that are > 127 (i.e. their high bit is set).
Bugs:
As with most quick hacks, the internals of this program are almost
completely undocumented. But it is a very simple program and
experienced C programmers should have no trouble following its
logic.
The following are some simple test strings:
Clear text _U_n_d_e_r_l_i_n_e_ _t_e_x_t Clear text
Clear text BBoolldd tteexxtt Clear text
Clear text _BB_oo_ll_dd_--_UU_nn_dd_ee_rr_ll_ii_nn_ee_ _tt_ee_xx_tt Clear text
Clear text BBBaaaddd ttteeexxxttt Clear text
Clear text B_Ba_ad_d _ t_te_ex_xt_t Clear text
******************************************************************************/
#include <stdio.h>
/* Type Definitions... */
enum TypeStyle {
kUndefinedStyle,
kPlain,
kBold,
kExtraBold,
kUltraBold,
kUnderline,
kBoldUnderline
};
typedef enum TypeStyle TypeStyle;
enum PageFormat {
kUndefinedPage,
kDefaultPage,
kFullPage10Point,
kHalfPage8Point,
kHalfPage7Point
};
typedef enum PageFormat PageFormat;
typedef unsigned char Char;
/* Function Prototypes... */
PageFormat ParseArguments (int, Char *[]);
void PrintHeader (PageFormat);
TypeStyle WhatStyle (Char *);
int CollectPlain (Char *, Char *);
int CollectBold (Char *, Char *);
int CollectExtraBold (Char *, Char *);
int CollectUltraBold (Char *, Char *);
int CollectUnderline (Char *, Char *);
int CollectBoldUnderline (Char *, Char *);
/* Global Constants... */
#ifdef applec
const Char kOpenSingleQuote = 'T'; /* Replace T with Option-] */
const Char kCloseSingleQuote = 'U'; /* Replace U with Shift-Option-] */
#else
const Char kOpenSingleQuote = 0xD4;
const Char kCloseSingleQuote = 0xD5;
#endif
/* Entry Point... */
main (int argc, Char *argv[])
{
int indexInLine;
int lengthInLine;
int (*collectChars)(Char *, Char *);
Char *styleCommand;
Char inLine [1024]; /* Actually, I believe these buffers need be */
Char outLine [1024]; /* only inLine [561], outLine [103], and */
Char pureChars [1024]; /* putChars [81]. But hey, memory is cheap. */
Char *fontCommand;
PageFormat fmt;
/* Parse the command line arguments */
fmt = ParseArguments (argc, argv);
if ( fmt == kUndefinedPage )
{
fprintf (stderr, "Invalid Argument\n");
fprintf (stderr,
"Usage: %s [-f | -h8 | -h7] <Man.file >RTF.File\n",
argv[0]);
return 0;
}
/* Print the appropriate header. */
PrintHeader (fmt);
/* Set up the font command string */
switch ( fmt )
{
case kFullPage10Point :
fontCommand = "\\f1\\fs20";
break;
case kHalfPage8Point :
fontCommand = "\\f1\\fs16";
break;
case kHalfPage7Point :
fontCommand = "\\f1\\fs14";
break;
case kDefaultPage :
case kUndefinedPage :
default :
fontCommand = "";
break;
}
/* Convert the file */
while ( gets(inLine) != NULL )
{
indexInLine = 0;
lengthInLine = strlen(inLine) + 1; /* Process the '\0' also. */
while ( indexInLine < lengthInLine )
{
switch ( WhatStyle (&inLine[indexInLine]) )
{
case kPlain :
collectChars = CollectPlain;
styleCommand = "";
break;
case kBold :
collectChars = CollectBold;
styleCommand = "\\b";
break;
case kExtraBold :
collectChars = CollectExtraBold;
styleCommand = "\\b";
break;
case kUltraBold :
collectChars = CollectUltraBold;
styleCommand = "\\b";
break;
case kUnderline :
collectChars = CollectUnderline;
styleCommand = "\\ul";
break;
case kBoldUnderline :
collectChars = CollectBoldUnderline;
styleCommand = "\\b\\ul";
break;
case kUndefinedStyle :
default :
fprintf (stderr,
"\nUnknown style returned from 'WhatStyle()'"
"\nIndex is %d"
"\nLine is \"%s\"\n",
indexInLine + 1, inLine);
inLine [indexInLine + 1] = '\0';
fprintf (stderr,"Error is %s^--Here\n",inLine);
return -1;
}
indexInLine += collectChars (&inLine[indexInLine], pureChars);
strcpy (outLine, "{\\plain");
strcat (outLine, fontCommand);
strcat (outLine, styleCommand);
strcat (outLine, " ");
strcat (outLine, pureChars);
strcat (outLine, "}");
puts (outLine);
}
}
/* Print trailer */
puts ("}");
return 0;
}
PageFormat ParseArguments (int argc, Char *argv[])
{
switch ( argc )
{
case 1 :
return kDefaultPage;
case 2 :
if ( strcmp (argv[1], "-f") == 0 )
return kFullPage10Point;
else if ( strcmp (argv[1], "-h8") == 0 )
return kHalfPage8Point;
else if ( strcmp (argv[1], "-h7") == 0 )
return kHalfPage7Point;
else
return kUndefinedPage;
default :
return kUndefinedPage;
}
}
void PrintHeader (PageFormat fmt)
{
puts ("{\\rtf0\\mac\\deff1");
puts ("{\\fonttbl{\\f0 \\fswiss Helvetica;}{\\f1 \\fmodern Courier;}}");
switch ( fmt )
{
case kFullPage10Point :
puts ("\\paperw12240\\paperh15840\\margt648\\margb648"
"\\margl1800\\margr0\\widowctrl\\ftnbj\\ftnrestart"
"\\ftnstart1\\pgnstart1\\deftab720\\fracwidth\\sectd"
"\\linemod0\\linex0\\cols1\\colsx863");
break;
case kHalfPage8Point :
puts ("\\paperw15840\\paperh12240\\landscape\\margt144"
"\\margb432\\margl144\\margr144\\widowctrl\\ftnbj"
"\\ftnrestart\\ftnstart1\\pgnstart1\\deftab720"
"\\fracwidth\\sectd\\linemod0\\linex0\\cols2\\colsx144");
break;
case kHalfPage7Point :
puts ("\\paperw15840\\paperh12240\\landscape\\margt1440"
"\\margb576\\margl720\\margr720\\widowctrl\\ftnbj"
"\\ftnrestart\\ftnstart1\\pgnstart1\\deftab720"
"\\fracwidth\\sectd\\linemod0\\linex0\\cols2\\colsx1080");
break;
case kUndefinedPage :
default :
break;
}
puts ("\\pard\\plain");
}
TypeStyle WhatStyle ( Char *line )
{
Char c1, c2, c3, c4, c5, c6, c7;
c1 = line [0];
c2 = line [1];
c3 = line [2];
c4 = line [3];
c5 = line [4];
c6 = line [5];
c7 = line [6];
if ( c1 == c3 && c3 == c5 && c5 ==c7
&& c2 == '\b' && c4 == '\b' && c6 == '\b'
&& c1 != '\0' )
return kUltraBold;
else if ( c1 == c3 && c3 == c5
&& c2 == '\b' && c4 == '\b'
&& c1 != '\0' )
return kExtraBold;
else if ( c1 == '_' && c3 == c5
&& c2 == '\b' && c4 == '\b'
&& c3 != '\0' )
return kBoldUnderline;
else if ( c1 == '_' && c2 == '\b' )
return kUnderline;
else if ( c1 == c3 && c2 == '\b' && c1 != '\0' )
return kBold;
else if ( c1 == '\b' || (c1 != '\0' && c2 == '\b') )
return kUndefinedStyle;
else
return kPlain;
}
int CollectPlain (Char *in, Char *out)
{
Char c;
Char *startPos;
startPos = in;
while ( 1 )
{
switch ( c = *in++ )
{
case '\b' :
*--out = '\0';
return (in - startPos) - 2;
case '\f' :
*out++ = '\\';
*out++ = 'p';
*out++ = 'a';
*out++ = 'g';
*out++ = 'e';
*out++ = ' ';
break;
case '`' :
*out++ = kOpenSingleQuote;
break;
case '\'' :
*out++ = kCloseSingleQuote;
break;
case '\0' :
*out++ = '\\';
*out++ = 'p';
*out++ = 'a';
*out++ = 'r';
*out++ = ' ';
*out = '\0';
return in - startPos;
case '{' :
*out++ = '\\';
*out++ = '{';
break;
case '}' :
*out++ = '\\';
*out++ = '}';
break;
case '\\' :
*out++ = '\\';
*out++ = '\\';
break;
default :
*out++ = c;
break;
}
}
}
int CollectBold (Char *in, Char *out)
{
Char c1, c2, c3;
Char *startPos;
startPos = in;
while ( 1 )
{
c1 = in [0];
c2 = in [1];
c3 = in [2];
if ( c1 != c3 || c2 != '\b' || c1 == '\0' )
{
*out = '\0';
return in - startPos;
}
else
{
in += 3;
switch ( c1 )
{
case '`' :
*out++ = kOpenSingleQuote;
break;
case '\'' :
*out++ = kCloseSingleQuote;
break;
case '{' :
*out++ = '\\';
*out++ = '{';
break;
case '}' :
*out++ = '\\';
*out++ = '}';
break;
case '\\' :
*out++ = '\\';
*out++ = '\\';
break;
default :
*out++ = c1;
break;
}
}
}
}
int CollectExtraBold (Char *in, Char *out)
{
Char c1, c2, c3, c4, c5;
Char *startPos;
startPos = in;
while ( 1 )
{
c1 = in [0];
c2 = in [1];
c3 = in [2];
c4 = in [3];
c5 = in [4];
if ( c1 != c3 || c3 != c5
|| c2 != '\b' || c4 != '\b'
|| c1 == '\0' )
{
*out = '\0';
return in - startPos;
}
else
{
in += 5;
switch ( c1 )
{
case '`' :
*out++ = kOpenSingleQuote;
break;
case '\'' :
*out++ = kCloseSingleQuote;
break;
case '{' :
*out++ = '\\';
*out++ = '{';
break;
case '}' :
*out++ = '\\';
*out++ = '}';
break;
case '\\' :
*out++ = '\\';
*out++ = '\\';
break;
default :
*out++ = c1;
break;
}
}
}
}
int CollectUltraBold (Char *in, Char *out)
{
Char c1, c2, c3, c4, c5, c6, c7;
Char *startPos;
startPos = in;
while ( 1 )
{
c1 = in [0];
c2 = in [1];
c3 = in [2];
c4 = in [3];
c5 = in [4];
c6 = in [5];
c7 = in [6];
if ( c1 != c3 || c3 != c5 || c5 != c7
|| c2 != '\b' || c4 != '\b' || c6 != '\b'
|| c1 == '\0' )
{
*out = '\0';
return in - startPos;
}
else
{
in += 7;
switch ( c1 )
{
case '`' :
*out++ = kOpenSingleQuote;
break;
case '\'' :
*out++ = kCloseSingleQuote;
break;
case '{' :
*out++ = '\\';
*out++ = '{';
break;
case '}' :
*out++ = '\\';
*out++ = '}';
break;
case '\\' :
*out++ = '\\';
*out++ = '\\';
break;
default :
*out++ = c1;
break;
}
}
}
}
int CollectUnderline (Char *in, Char *out)
{
Char c1, c2, c3;
Char *startPos;
startPos = in;
while ( 1 )
{
c1 = in [0];
c2 = in [1];
c3 = in [2];
if ( c1 != '_' || c2 != '\b' || c3 == '\0' )
{
*out = '\0';
return in - startPos;
}
else
{
in += 3;
switch ( c3 )
{
case '`' :
*out++ = kOpenSingleQuote;
break;
case '\'' :
*out++ = kCloseSingleQuote;
break;
case '{' :
*out++ = '\\';
*out++ = '{';
break;
case '}' :
*out++ = '\\';
*out++ = '}';
break;
case '\\' :
*out++ = '\\';
*out++ = '\\';
break;
default :
*out++ = c3;
break;
}
}
}
}
int CollectBoldUnderline (Char *in, Char *out)
{
Char c1, c2, c3, c4, c5;
Char *startPos;
startPos = in;
while ( 1 )
{
c1 = in [0];
c2 = in [1];
c3 = in [2];
c4 = in [3];
c5 = in [4];
if ( c1 != '_' || c2 != '\b' || c4 != '\b' || c3 != c5 || c3 == '\0' )
{
*out = '\0';
return in - startPos;
}
else
{
in += 5;
switch ( c3 )
{
case '`' :
*out++ = kOpenSingleQuote;
break;
case '\'' :
*out++ = kCloseSingleQuote;
break;
case '{' :
*out++ = '\\';
*out++ = '{';
break;
case '}' :
*out++ = '\\';
*out++ = '}';
break;
case '\\' :
*out++ = '\\';
*out++ = '\\';
break;
default :
*out++ = c3;
break;
}
}
}
}