/*
* fmtr - formatter for web pages...
*
* Created by: Jack C Lipton (see http://www.asstr.org/~CupaSoup/
*
* Some notes:
*
* Input paragraphs are NOT indented; tab-based indented
* lines are discarded.
*
* Paragraphs are separated by a blank line.
*
* *word* emboldens the "word" (or words).
*
* _word_ emphasises the "word" (or words) via bold+italics.
*
* |line will set the line as "centered.
*
* _ alone on a line will emit '
/*
* Provide early location for compiled-in global overrides
*/
/* #define OVERRIDE_AUTHOR "Jack C Lipton"*/
#define WEB_AUTHORNAME "Jack C Lipton"
#define WEB_AUTHOREMAIL "cupasoup@pele.cx"
#define WEB_ROOTDIR "http://www.asstr.org/~CupaSoup/"
#define WEB_SERIALNO "CXNRITNZQLQQBDITGAVD"
#define COPYRIGHT_HEADING "2002, 2003, 2004, 2005 Jack C Lipton"
/*
* Manifest constants (stupid, yes.)
*/
#define INBUFSIZE 4096
/*
* These are used in generating the "snippet" for the
* Reader's Rate/Review system and the copyright notice.
* (Note that the "Copyright (c)" with the circle around
* the "c" is embedded in the putFini() logic.)
*
* Each author needs to tune this for themselves.
*/
#if 1
char web_authorname[512];
char web_authoremail[512];
char web_rootdir[512];
char web_serial_number[256];
#else
char *web_authorname = WEB_AUTHORNAME;
char *web_authoremail = WEB_AUTHOREMAIL;
char *web_rootdir = WEB_ROOTDIR;
char *web_serial_number = WEB_SERIALNO;
#endif
char author_override[512];
#if defined(LIX_ENABLED)
char *acrrs_url =
"http://cgi.tripod.com/lixdw1192/cgi-bin/loadeval.pl";
#endif
char *copyright_heading = COPYRIGHT_HEADING;
char *copyright_body = "All rights reserved. Please contact author for other use.";
char web_page_name[512];
char corename[512];
char next_page_name[512];
char prev_page_name[512];
/*
* SHS Formats for publication
*
* |Author:
* |Title:
* |Part:
* |Universe:
* |Summary:
* |Keywords:
* |Revision: $Revision: 1.19 $
* |Archive:
* |Mailing List:
* |FAQ:
* |RCS: $Id: fmtr.c,v 1.19 2006/07/20 21:19:48 jcl Exp jcl $
*
*/
char shs_authorname[1024];
char shs_title[1024];
char shs_part[1024];
char shs_universe[1024];
char shs_summary[4096];
char shs_keywords[1024];
char shs_revision[1024];
char shs_archive[1024];
char shs_mailinglist[1024];
char shs_faq[1024];
char shs_rcs[1024];
/*
* Here's the structure I use to map the tag names and point to
* the buffers, above; This makes the logic to fill the buffers
* that much easier.
*
* Yes, this is awkward and I might have been able to do better.
*/
struct MapItems {
char *label; /* label part of SHS line */
int lablen, /* length of label to check */
buflen; /* length of the buffer */
char *buffer; /* pointer to buffer */
};
struct MapItems shsInfo[] = {
{ "Author:", 7, 1024, shs_authorname },
{ "Title:", 6, 1024, shs_title },
{ "Part:", 5, 1024, shs_part },
{ "Universe:", 9, 1024, shs_universe },
{ "Summary:", 8, 4096, shs_summary },
{ "Keywords:", 9, 1024, shs_keywords },
{ "Revision:", 9, 1024, shs_revision },
{ "Archive:", 8, 1024, shs_archive },
{ "Mailing List:", 13, 1024, shs_mailinglist },
{ "FAQ:", 4, 1024, shs_faq },
{ "RCS:", 4, 1024, shs_rcs },
{ NULL, 0, 0, NULL }
};
/*
* Handle baseline emphasis logic
*/
char *emphasizers[2] = { "", "" };
char *bolders[2] = { "", "" };
static int bolding = 0,
emphasized = 0;
static int leadin_skip = 1;
static int consec_blank = 0; /* consecutive blank lines */
static int force_fb_form = 0; /* force creation of fb file */
/*
* A fill_mode of zero indicates normal delivery of the file; a 1
* will cause each input line to get a line break (which is really
* needed when delivering poetry).
* What's interesting is that someday I'll want to be able to flip
* this on-and-off on the fly via embedded operations, but that can
* wait...
*/
int fill_mode = 0; /* assume normal wrapping */
int adultflag = 1; /* assume ADULTSONLY tag */
int asstrflag = 1; /* generate HTML for ASSTR */
int ewpubflag = 0; /* generate HTML for EWP.ORG */
int fini_flag = 1; /* assume one complete part */
char SecName[256]; /* section name (Universe) */
/*
* Some things really want to have function prototypes to shut
* up all of the warning messages I keep getting...
*/
extern char *basename( char *);
extern char *dirname( char *);
extern char *strchr( char *, char);
extern char *strrchr( char *, char);
extern char *malloc( unsigned int);
extern char *strstr( char *, char *);
/*
* Here are the function prototypes so that all forward references
* won't bitch and moan about function typing...
*/
int cvtFile( char *, FILE *, FILE *); /* convert text part of a file */
int cvtLine( FILE *, char *); /* convert a text ling from a file */
int procSHS( char *, FILE *, FILE *, char *); /* digest SHS */
void put_acrrs_snippet( FILE *); /* insert rate/review button */
void putFini( FILE *); /* put appropriate ending on webfile */
int FindInBuffer( char *, char *); /* scan buffer for matching contents */
int mkFBform( char *); /* generate HTML feedback form */
int appendFBform( FILE *, char *); /* append a feedback form */
main( argc, argv, envp) /* formatter utility */
int argc;
char *argv[];
char *envp[];
{
int a; /* arglist index */
char textpath[1024], /* path name of input file */
webpath[1024], /* path of output file w/ + */
oldwebpage[1024]; /* assumed name of base page */
FILE *textfile, /* input file handle/pointer */
*webfile; /* resultant file pointer */
/*
* Set default values for all global variables...
*/
fill_mode = 0; /* ensure default fill mode */
strcpy( next_page_name, "");
strcpy( prev_page_name, "");
#if defined(WEB_AUTHORNAME)
strcpy( web_authorname, WEB_AUTHORNAME);
strcpy( web_authoremail, WEB_AUTHOREMAIL);
strcpy( web_rootdir, WEB_ROOTDIR);
strcpy( web_serial_number, WEB_SERIALNO);
#else
strcpy( web_authorname, "");
strcpy( web_authoremail, "");
strcpy( web_rootdir, "");
strcpy( web_serial_number, "");
#endif
#if defined(OVERRIDE_AUTHOR)
strcpy( author_override, OVERRIDE_AUTHOR);/* allow for global change */
#else
strcpy( author_override, "");
#endif
/*
* Work through the arglist, handling options that change
* the behavior of this text file filter.
*/
for ( a = 1 ; a < argc ; a++ )
{
if ( argv[a][0] == '-' )
{
switch( argv[a][1])
{
case 'I': /* override who "I" am */
if ( strlen( argv[a]) > 2 )
strcpy( author_override, &argv[a][2]);
else
strcpy( author_override, argv[++a]);
break;
case 'w': /* word fill */
fill_mode = 0;
break;
case 'l': /* line mode (for poetry) */
fill_mode = 1;
break;
case 'A': /* turn off ADULTSONLY tag */
adultflag = 0;
break;
case 'a': /* turn on ADULTSONLY tag */
adultflag = 1;
break;
case 'P': /* previous file's name */
if ( strlen(argv[a]) > 2 )
strcpy( prev_page_name, &argv[a][2]);
else
strcpy( prev_page_name, argv[++a]);
break;
case 'N': /* next file's name */
if ( strlen(argv[a]) > 2 )
strcpy( next_page_name, &argv[a][2]);
else
strcpy( next_page_name, argv[++a]);
break;
case 'e': /* target EWPUB not ASSTR */
asstrflag = 0;
ewpubflag = 1;
adultflag = 0;
break;
case 'E': /* target ASSTR not EWPUB */
asstrflag = 1;
ewpubflag = 0;
adultflag = 1;
break;
}
}
else /* process the file as named */
{
int rc;
char *cp;
char cmdline[512];
/*
* We need to synthesize the target named from
* the input name.
*/
strcpy( textpath, argv[a]); /* copy in the name */
textfile = fopen( textpath, "r");
/*
* If we can't open the input file we can
* give up trying to write something...
*/
if ( !textfile )
{
fprintf( stderr,
"Could not open [%s] for reading.\n",
textpath);
fflush( stderr);
exit( 1);
}
/*
* capture the name of the file w/o extensions
* (ie. no .txt, .x, or whatnot) and without
* the directory part (should it be present).
*/
strcpy( corename, basename(textpath));
cp = strrchr( corename, '.');
if ( cp && *cp ) { *cp = 0x00; }
/*
* Synthesize the name we'll be outputting to;
* it'll be a dir/corename.html+ so that we
* can choose whether to do a cutover (or not).
*/
strcpy( web_page_name, corename);
strcpy( webpath, dirname( textpath));
strcat( webpath, "/");
strcat( webpath, corename);
strcat( webpath, ".html");
strcpy( oldwebpage, webpath); /* name for compare */
strcat( webpath, "+"); /* new name */
/*
* Report on the start of the conversion process
*/
#if defined(BE_VERBOSE)
fprintf( stderr, "%s ... ", corename);
fflush( stderr);
#endif
webfile = fopen( webpath, "w");
fini_flag = 1; /* assume completed */
if ( !webfile )
{
/*
* if we fail to open output, puke it up
*/
fclose( textfile);
fprintf( stderr,
"Could not open [%s] for writing.\n",
webpath);
fflush( stderr);
exit( 2);
}
/*
* Now we can convert the file. The cvtFile()
* function will digest the SHS headers and
* then process the actual text. When the
* input file has been finished the putFini()
* call closes it out.
*/
cvtFile( corename, textfile, webfile);
putFini( webfile);
#if defined(BE_VERBOSE)
fprintf( stderr, "\n"); /* indicate completion */
fflush( stderr);
#endif
/*
* Done with the files, close 'em
*/
fclose( textfile);
fclose( webfile);
/*
* We want to make the "cutover" process a
* conditional one; if no changes have been
* made, we want to skip the cutover.
*/
sprintf( cmdline, "diff %s %s >/dev/null",
oldwebpage, webpath);
rc = system( cmdline);
/*
* If the diff command exited w/ a zer0, there's
* no differences, so we'll ditch the new file
* since there's no point to cutting over a file
* that has no differences.
*/
if ( rc == 0 ) /* files are identical */
{
unlink( webpath); /* discard redundant */
}
else
{
sprintf( cmdline, "cutover %s", oldwebpage);
system( cmdline);
}
}
}
exit( 0);
} /* fmtr main */
/*
* procSHS - This function reads in the source file's SHS
* (Standard Header Sequence) for ASSTR which is
* intended to keep the story meta-information in
* proximity to the actual story content. It is
* hoped this will not be clipped since it keeps
* the most useful information in a recognizable
* form.
*/
int
procSHS( corename, si, so, inbuf) /* process SHS headers and populate table */
char *corename; /* used to check for importable item */
FILE *si, /* flat ascii w/ SHS-based prefix */
*so; /* resultant HTML file to be filled */
char *inbuf; /* line that broke the SHS scanning */
{
int i, /* index into SHS map table */
llen; /* line length as seen */
char *cp; /* utility pointer */
char importname[4096]; /* name for imported objects */
/*
* Before processing the open file we need to clear the
* target buffers
*/
for ( i = 0 ; shsInfo[i].buflen > 0 ; i++ ) /* clear previous */
{
strcpy( shsInfo[i].buffer, "");
}
/*
* Read lines from the file and scan them for leadin
* SHS lines...
*/
while ( fgets( inbuf, 4095, si) )
{
llen = strlen( inbuf);
inbuf[--llen] = 0x00; /* drop the newline */
/*
* Detect changes that will indicate the end of
* the heading section...
*/
if ( llen == 0 ) break;
if ( inbuf[0] == ' ' ) break;
if ( inbuf[0] == '\t' ) break;
/*
* OK, scan the input buffer against the list of
* labels we're looking to deal with.
*/
for ( i = 0 ; shsInfo[i].buflen > 0 ; i++ )
{
struct MapItems *map;
map = &shsInfo[i];
/*
* If the label matches, we'll process it
* properly by finding the data part...
*/
if ( strncmp( inbuf, map->label, map->lablen ) == 0 )
{
char *cp;
cp = strchr( inbuf, ':');
if ( cp && *cp ) cp++;
if ( cp && *cp ) cp++;
strncpy( map->buffer, cp, map->buflen);
break;
}
}
}
/*
* Provide opportunity to process non-RCS updates
* (Any overrides that are either compiled in or have been
* added to the command line in the make file.)
*/
if ( *author_override ) /* is this a non-empty string? */
{
strcpy( shs_authorname, author_override);
}
/*
* Note: I need this code to scratch a bogus part of
* the Author: line without me having to go
* back in to each file just to remove an email
* address from the SHS headers.
*/
cp = shs_authorname;
while ( cp
&& *cp
&& ( *cp != '<' ) )
{
cp++;
}
if ( *cp == '<' ) /* e-mail address present? */
{
*cp-- = '\0';
if ( ( *cp == ' ' ) || ( *cp == '\t' ) )
{
*cp = '\0';
}
}
/*
* All the SHS information has been accumulated at this point
* so we can now start generating the web-formatted file.
*
* Note that this is ancient HTML, capiche?
*/
fprintf( so, "\n");
fprintf( so, "\n\n\n");
fprintf( so, " %s \n\n", shs_title);
/*
* The following tag is assumed for content on ASSTR
* (I'm not really sure how this _should_ be done, BTW)
* I've implementest this as a conditional so that it
* can be turned off for other content.
*/
if ( adultflag )
{
fprintf( so, "\n");
}
/*
* Here we fill in the Meta information we've accumulated
* from the SHS headers, as recommended by others.
*/
if ( asstrflag != 0 )
{
fprintf( so, "\n", shs_title);
fprintf( so, "\n", shs_part);
fprintf( so, "\n", shs_authorname);
fprintf( so, "\n", shs_keywords);
#if 0
fprintf( so, "\n", "`date`");
#endif
fprintf( so, "\n", shs_universe);
fprintf( so, "\n", shs_summary);
fprintf( so, "\n", shs_revision);
}
fprintf( so, "\n");
if ( ewpubflag == 1 )
{
fprintf( so, "\n\n");
}
else
{
FILE *insertable;
char insertbuf[4096];
fprintf( so, "\n\n");
/*
* Insert the contents of "web.prefix" at this point
*/
insertable = fopen( "web.prefix", "r");
while ( insertable && fgets( insertbuf, 4095, insertable) )
{
fputs( insertbuf, so); /* copy line out */
}
if ( insertable )
fclose( insertable);
}
/*
* Now we can start populating the actual content of the
* web page by plugging in the initial H1 header.
*/
fprintf( so, "\n");
fprintf( so, "%s\n", shs_title);
if ( strcmp( shs_part, "") != 0 )
{
fprintf( so, "(part %s)\n", shs_part);
}
fprintf( so, "
\n");
fprintf( so, "\n");
/*
* With the title out of the way we can now present the
* remainder:
* Keywords;
* Author's MAILTO and name;
* Main Page back-link;
* Rate/Review button (if enabled).
*/
if ( strcmp( shs_keywords, "" ) != 0 )
{
fprintf( so, "codes: %s\t
\n", shs_keywords);
}
#if 0
fprintf( so, "by %s
\n",
web_authoremail, web_authorname);
#else
fprintf( so, "by %s
\n", shs_authorname);
#endif
if ( asstrflag != 0 )
{
fprintf( so, "(Main Page)
\n");
}
if ( strlen( prev_page_name) != 0 )
{
fprintf( so, " Previous Chapter
\n",
prev_page_name);
}
fflush( so);
fprintf( so, "\n");
fprintf( so, "
\n");
#if 0
if ( asstrflag != 0 )
put_acrrs_snippet( so);
#endif
fprintf( so, "
\n");
fflush( so);
/*
* If we find a "(SecName).preface" file present we want to
* merge it into the resultant stream at this point. This
* allows acknowledgements to be assembled dynamically.
*/
strcpy( SecName, "");
if ( shs_universe[0] )
{
FILE *pf;
char *cp = shs_universe;
char *dp = SecName;
char preface_path[512];
while ( cp && *cp && (*cp != ' ') )
*dp++ = *cp++;
*dp = 0x00;
sprintf( preface_path, "%s.preface", SecName);
pf = fopen( preface_path, "r");
if ( pf )
{
char iobuf[4096];
while ( fgets( iobuf, 4095, pf) )
fputs( iobuf, so);
fclose( pf);
}
}
/*
* Cheat - check for a specific prefix
*/
{
FILE *pf;
char importName[4096];
sprintf( importname, "%s.prefix", corename);
pf = fopen( importname, "r");
if ( pf )
{
char iobuf[4096];
while ( fgets( iobuf, 4095, pf) )
fputs( iobuf, so);
fclose( pf);
}
}
/*
* We make a pass through the shs_title to check for an
* incomplete work (where the word "incomplete" will be
* in the 'Title:' line):
*/
fini_flag = ( FindInBuffer(shs_title, "(incomplete)") == 0 );
/*
* Now we're ready for the game
* PLEASE NOTE: the first non-header line is left inside the
* "inbuf" buffer zone where the cvtLine() function can then
* digest it.
*/
return( 0);
} /* procSHS */
/*
* This function inserts the Rate/Review button into the web page
* being generated.
*/
void
put_acrrs_snippet( so) /* insert a rate/review button */
FILE *so;
{
#if defined(LIX_ENABLED)
fprintf( so,
"");
#else
# if 1
# if 1
appendFBform( so, shs_title); /* generate feedback form file */
# else
mkFBform( shs_title); /* generate feedback form file */
fprintf( so,
" Comment on this story \n",
corename);
# endif
# else
fprintf( so,
"Comment on this story\n");
# endif
#endif
} /* put_acrrs_snippet */
/*
* cvtLine - (Convert Line) tags a buffer and parses it out
* into HTML for reading.
*/
int
cvtLine( so, inbuf) /* process content of the targetted text line */
FILE *so;
char *inbuf;
{
int llen, /* chars in input buffer */
centered; /* centering tag was found */
char lastchar; /* last character processed */
char *cp; /* copy character pointer */
cp = inbuf; /* point to start of buffer */
/*
* Detect a line we need to completely ignore.
*/
if ( strncmp( cp, "//", 2) == 0 ) /* no action, meta info */
return( 0); /* this won't even break a paragraph */
/*
* Sneak in a link button to next/previous page
*/
if ( *cp == '>' ) /* button configuration line */
{
/*
* >file:label
*/
char nextfile[512];
char label[512];
char *dp;
/*
* grab the name of the file to be linked
*/
cp++;
dp = nextfile;
while ( cp && *cp && (*cp != ':') )
*dp++ = *cp++;
*dp = 0x00;
cp++; /* skip the ':' delimiter */
/*
* now grab the name to be placed as the link
*/
dp = label;
while ( cp && *cp )
*dp++ = *cp++;
*dp = 0x00;
/*
* Next we'll sneak it into the output
*/
fprintf( so, " %s ", nextfile, label);
}
/*
* Recognize the left-margin marker that tells us
* to center the rest of the line.
*/
if ( *cp == '|' ) /* tells formatter to center this line */
{
cp++; /* skip the marker */
fputs( "
", so); /* start centering for line */
centered = 1;
}
else
centered = 0;
/*
* Recognize when a '_' is alone at the left margin; that
* tells us to generate a horizontal line as a break point.
*/
if ( strcmp( inbuf, "_") == 0 )
{
fputs( "
\n", so);
leadin_skip = 0;
consec_blank = 0;
return( 0);
}
/*
* Some more special defects...
* a { alone on a line will turn on the fill-mode
* a } alone on a line will turn off the
per line
*/
if ( strcmp( inbuf, "{") == 0 )
{
fputs( "\n", so);
fill_mode = 1;
return( 0);
}
if ( strcmp( inbuf, "}") == 0 )
{
fputs( "\n", so);
fill_mode = 0;
return( 0);
}
/*
* I will not have even one tab character in front of a line
* containing significant text to be processed, so we'll
* detect such lines, treat them as paragraph breaks, and
* return having processed the line.
*/
if ( ( *cp == '\0' ) /* zero-length line */
#if 1
|| ( *cp == '\t' ) /* detect first tab char */
#else
|| ( strncmp( inbuf, "\t\t", 2) == 0 ) /* multiple tabs? */
#endif
)
{
fprintf( so, "\n");
if ( bolding > 0 )
{
fprintf( so, "%s\n", bolders[bolding]);
bolding ^= 1;
}
if ( emphasized > 0 )
{
fprintf( so, "%s\n", emphasizers[emphasized--]);
emphasized ^= 1;
}
#if 0
if ( ( leadin_skip == 0 )
|| ( consec_blank++ < 2 ) )
#else
if ( consec_blank++ < 1 )
#endif
{
if ( fill_mode != 0 ) { fprintf( so, "
\n"); }
else { fprintf( so, "\n"); }
}
return( 0);
}
leadin_skip = 0; /* turn off leadin suppression */
consec_blank = 0;
/*
* Since the line has significant text, we'll process it
* looking for the "emphasis" indicators...
*/
lastchar = '\0'; /* a NUL to indicate left margin */
while ( cp && *cp )
{
char gotc;
gotc = *cp++;
if ( ( gotc == '\134' ) /* skip over an escape char */
&& ( lastchar != '\134' ) ) /* that wasn't escape */
{
lastchar = gotc;
continue;
}
/*
* Note: The characters used for various special
* defects should really be done using a
* table but this cut is primitive enough
* that I'm not desperate to use.
*/
/*
* Recognize a bold enter/leave tag
*/
#if 0
if ( gotc == '*' ) /* detect emphasis */
#else
if ( ( gotc == '*' ) /* unescaped emphasis */
&& ( lastchar != '\134' ) )
#endif
{
fprintf( so, "%s", bolders[bolding]);
bolding ^= 1;
continue;
}
/*
* Recognize an emphasize enter/leave tag
*/
#if 0
if ( gotc == '_' )
#else
if ( ( gotc == '_' ) /* unescaped emphasis */
&& ( lastchar != '\134' ) )
#endif
{
fprintf( so, "%s",emphasizers[emphasized]);
emphasized ^= 1;
continue;
}
/*
* If we didn't have to remap the character, we'll
* just pass it through unmolested.
*/
fputc( gotc, so); /* put out the literal char */
lastchar = gotc;
}
/*
* Based on whether fill_mode has been set, we choose to
* append a line BReak for each input line
*/
if ( fill_mode != 0 ) { fprintf( so, "
\n"); }
else { fprintf( so, " \n"); }
/*
* If we got centered we want to turn it off here.
*/
if ( centered ) fputs( "
\n", so);
return( 1);
} /* cvtLile */
/*
* cvtFile - Given an input (text) file handle and an output
* (web format) file handle, this will manage the
* processing of the SHS headings and generates the
* necessary HTML content.
*/
int
cvtFile( corename, si, so) /* process content of the target text file */
char *corename;
FILE *si,
*so;
{
int lines,
llen;
char importname[4096]; /* name for imported objects */
char inbuf[INBUFSIZE]; /* buffer for input text */
char outbuf[8192]; /* buffer for html output */
char *cp, /* copy character pointer */
*dp, /* --> destination buffer */
*twp,
*nwp;
bolding = 0;
emphasized = 0;
consec_blank = 0;
lines = 0; /* reset the count of lines */
procSHS( corename, si, so, inbuf); /* leaves first non-hdr in inbuf */
leadin_skip = 1; /* we want to suppress stuff */
cvtLine( so, inbuf); /* pass captured line */
lines++;
/*
* While we still have contents, pass the line for conversion
*/
while ( fgets( inbuf, 4095, si ) )
{
llen = strlen( inbuf);
inbuf[--llen] = 0x00; /* remove the linefeed */
lines++;
cvtLine( so, inbuf); /* do the line conversion */
}
return( 0);
} /* cvtFile */
/*
* putFini - Handles closure of the generate Web Page which
* includes the Rate/Review button, a copyright
* notice, and a flat copy of the actual SHS headers.
*/
void
putFini( so)
FILE *so;
{
int i;
fprintf( so, "
\n");
if ( strlen( next_page_name) != 0 )
{
fprintf( so, " Next Chapter
\n",
next_page_name);
}
else
{
int this_part = -1,
last_part = -2;
/*
* We'll re-check the part information for "Fini" flag...
* Part information is formated part/total, so...
* 12/12
* will justify a "Fini" whilst
* 10/12
* won't (but, really, this should have been covered
* by the prev/next link info, above).
*/
if ( strlen( shs_part) > 0 )
{
char *cp;
cp = shs_part;
while ( cp && *cp && (*cp == ' ') )
cp++; /* skip any leading blanks */
/*
* Too lazy to fix (xx/xx) damnit...
*/
if ( cp && *cp && (*cp == '(') )
cp++;
if ( cp && *cp )
{
this_part = atoi(cp);
cp = strchr( cp, '/');
if ( cp && *cp )
{
cp++; /* skip the slash */
while ( cp && *cp && (*cp == ' ') )
cp++;
if ( cp && *cp )
last_part = atoi(cp);
}
}
/*
* check the collected info
*/
if ( this_part == last_part )
fini_flag = 1;
}
/*
* generate the "default" closing
*/
if ( fini_flag != 0 )
{
fprintf( so, "
* Fini *
\n");
}
else
{
fprintf( so, "
* (To Be Continued) *
\n");
}
}
fprintf( so, "
\n");
fprintf( so, "\n\n");
fprintf( so, "
\n");
if ( asstrflag != 0 )
put_acrrs_snippet( so); /* Rate/Review button */
fprintf( so, "
\n
\n");
/*
* Insert the Copyright notice
*/
fprintf( so, "Copyright © %s\n", copyright_heading);
fprintf( so, "%s\n
\n
\n", copyright_body);
fprintf( so, "
\n");
/*
* Insert the contents of "web.suffix" at this point
*/
{
FILE *insertable;
char insertbuf[4096];
insertable = fopen( "web.suffix", "r");
while ( insertable && fgets( insertbuf, 4095, insertable) )
{
fputs( insertbuf, so); /* copy line out */
}
if ( insertable )
fclose( insertable);
}
/*
* Now we deliver the original SHS contents to the tail
* end of the web page. We pull the contents back from
* the shsInfo table.
*/
if ( asstrflag != 0 )
{
fprintf( so, "\n");
for ( i = 0 ; shsInfo[i].buflen > 0 ; i++ )
{
struct MapItems *map;
char *cp,
ch;
map = &shsInfo[i];
fprintf( so, "%s ", map->label);
cp = map->buffer;
while ( cp && *cp )
{
if ( *cp == '<' )
{
fputs( "<", so);
}
else if ( *cp == '>' )
{
fputs( ">", so);
}
else
fputc( *cp, so);
cp++;
}
fputs( "\n", so);
}
fprintf( so, "
\n");
}
fprintf( so, "\n\n\n\n"); /* emit HTML closure */
} /* putFini */
int
FindInBuffer( buffer, look4) /* look for a pattern */
char *buffer;
char *look4;
{
unsigned int isize;
char *tbuf; /* temp buffer space */
char *sp, /* source buffer */
*dp, /* copy to buffer */
*tp, /* test pointer */
ch;
/*
* make a case-limited version
*/
isize = strlen( buffer); /* get size of existing */
isize += 4; /* pad this up */
tbuf = malloc( isize); /* build up a buffer */
dp = tbuf; /* point to local copy */
sp = buffer; /* point to original */
while ( sp && *sp ) /* does a copy as lower text */
{
ch = *sp++;
if ( isupper( ch) )
*dp++ = tolower( ch);
else
*dp++ = ch;
}
*dp = 0x00; /* terminate temp buffer */
sp = strstr( tbuf, look4); /* look for a match */
free( tbuf); /* release temp space */
if ( sp && *sp ) /* recognize successful copy */
return( 1);
return( 0);
} /* FindInBuffer */
int
mkFBform( title) /* generate an HTML feedback form */
char *title; /* title to pre-fill form */
{
FILE *so; /* file for generated form */
char fbpath[512]; /* name of generated form */
sprintf( fbpath, "fb-%s.html", corename);
/*
* If the feedback form file already exists don't step on it
*/
if ( ( force_fb_form == 0 ) && ( access( fbpath, 04) == 0 ) )
{
return( 0);
}
/*
* Open the file where we'll place the feedback form
*/
so = fopen( fbpath, "w");
/*
* Populate the file with the appropriate HTML
*/
fprintf( so, "\
\n\
\n\
\n\
\n\
\n\
\n");
fprintf( so, "\
Jack Lipton's Feedback Form for %s\n\
\n\n",
title);
fprintf( so, "\
\n\
Jack C Lipton's Feedback Form for %s\n\
\n\
\n",
title);
fprintf( so, "\
A Message to my Readers
\n\
\n\
Thank you for reading my stories.\n\
\n\
This page is how the ASSTR.ORG site\n\
provides the capability to send your comments\n\
to me anonymously.\n\
However, if you would like me to respond, you may\n\
provide a return e-mail address.\n\
If you ask me questions I can only answer if a\n\
working e-mail address is provided.\n\
\n");
fprintf( so, "\
Why provide feedback?
\n\
\n\
Feedback is the lifeblood of authors here on ASSTR.ORG;\n\
we don't get paid in any currency beyond hits on the\n\
pages and feedback from our readership.\n\
Encouragement, questions, critiques, typos... as a\n\
reader you may be surprised how much your words mean to us.\n\
\n\
This page gives you the opportunity to tell me what\n\
you thought of the words I've written...\n\
\n\
It is a good feeling to have my words read.\n\
\n");
fprintf( so, "\
Here's your turn to talk to me
\n\
\n");
fprintf( so, "\
\n\
\n\
If the above does not work for you, try:\n\
ASSTR Msg Form\n\
\n\
\n\
\n