--- loncom/cgi/mimeTeX/mimetex.c 2007/10/09 21:41:41 1.3
+++ loncom/cgi/mimeTeX/mimetex.c 2008/12/04 12:17:13 1.4
@@ -1,10 +1,11 @@
/****************************************************************************
*
- * Copyright(c) 2002-2006, John Forkosh Associates, Inc. All rights reserved.
+ * Copyright(c) 2002-2008, John Forkosh Associates, Inc. All rights reserved.
+ * http://www.forkosh.com mailto: john@forkosh.com
* --------------------------------------------------------------------------
* This file is part of mimeTeX, which is free software. You may redistribute
* and/or modify it under the terms of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
+ * version 3 or later, as published by the Free Software Foundation.
* MimeTeX is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY, not even the implied warranty of MERCHANTABILITY.
* See the GNU General Public License for specific details.
@@ -12,10 +13,11 @@
* agreed to these terms and conditions, and that you possess the legal
* right and ability to enter into this agreement and to use mimeTeX
* in accordance with it.
- * Your mimeTeX distribution should contain a copy of the GNU General
- * Public License. If not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
- * or point your browser to http://www.gnu.org/licenses/gpl.html
+ * Your mimetex.zip distribution file should contain the file COPYING,
+ * an ascii text copy of the GNU General Public License, version 3.
+ * If not, point your browser to http://www.gnu.org/licenses/
+ * or write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
* --------------------------------------------------------------------------
*
* Purpose: o MimeTeX, licensed under the gpl, lets you easily embed
@@ -25,23 +27,29 @@
* entirely separate little program that doesn't use TeX or
* its fonts in any way. It's just one cgi that you put in
* your site's cgi-bin/ directory, with no other dependencies.
- * So mimeTeX is very easy to install. And it's equally easy
- * to use. Just place an html tag in your document
+ * So mimeTeX is very easy to install. And it's equally
+ * easy to use. Just place an html tag in your document
* wherever you want to see the corresponding LaTeX expression.
* For example,
*
* immediately generates the corresponding gif image on-the-fly,
* displaying the rendered expression wherever you put that
- * tag. MimeTeX doesn't need intermediate dvi-to-gif
- * conversion, and it doesn't clutter up your filesystem with
- * separate little gif files for each converted expression.
+ * tag.
+ * MimeTeX doesn't need intermediate dvi-to-gif conversion,
+ * and it doesn't clutter up your filesystem with separate
+ * little gif files for each converted expression.
* But image caching is available by using mimeTeX's
* -DCACHEPATH=\"path/\" compile option (see below).
* There's also no inherent need to repeatedly write the
* cumbersome tag illustrated above. You can write
* your own custom tags, or write a wrapper script around
* mimeTeX to simplify the notation.
+ * Further discussion about mimeTeX's features and
+ * usage is available on its homepage,
+ * http://www.forkosh.com/mimetex.html
+ * and similarly in mimetex.html included with your mimetex.zip
+ * distribution file.
*
* Functions: ===================== Raster Functions ======================
* PART2 --- raster constructor functions ---
@@ -188,13 +196,13 @@
* ismonth(month) is month current month ("jan"-"dec")?
* unescape_url(url,isescape), x2c(what) xlate %xx url-encoded
* logger(fp,msglevel,logvars) logs environment variables
- * emitcache(cachefile,maxage,isbuffer) emit cachefile to stdout
+ * emitcache(cachefile,maxage,valign,isbuffer) emit cachefile
* readcachefile(cachefile,buffer) read cachefile into buffer
* md5str(instr) md5 hash library functions
* GetPixel(x,y) callback function for gifsave library
*
* Source: mimetex.c (needs mimetex.h and texfonts.h to compile,
- * and also needs gifsave.c if compiled with -DAA or -DGIF)
+ * and also needs gifsave.c when compiled with -DAA or -DGIF)
*
* --------------------------------------------------------------------------
* Notes o See bottom of file for main() driver (and "friends"),
@@ -211,9 +219,10 @@
* and with -DAA or -DGIF you'll also need gifsave.c
* o For gif images, the gifsave.c library by Sverre H. Huseby
* slightly modified by me to allow
- * (a)sending output to stdout and (b)specifying a transparent
- * background color index, is included with mimeTeX,
- * and it's documented in mimetex.html#gifsave .
+ * (a)sending output to stdout or returning it in memory,
+ * and (b)specifying a transparent background color index,
+ * is included with mimeTeX, and it's documented in
+ * mimetex.html#gifsave .
* o Optional compile-line -D defined symbols are documented
* in mimetex.html#options . They include (additional -D
* switches are discussed in mimetex.html#options)...
@@ -332,7 +341,8 @@
* 10/02/04 J.Forkosh Version 1.50 released.
* 11/30/04 J.Forkosh Version 1.60 released.
* 10/11/05 J.Forkosh Version 1.64 released.
- * 11/30/06 J.Forkosh most recent changes
+ * 11/30/06 J.Forkosh Version 1.65 released.
+ * 09/06/08 J.Forkosh Version 1.70 released.
*
****************************************************************************/
@@ -669,7 +679,6 @@ GLOBAL(char,*subexprptr,(char *)NULL); /
/*SHARED(int,imageformat,1);*/ /* image is 1=bitmap, 2=.gf-like */
GLOBAL(int,isdisplaystyle,1); /* displaystyle mode (forced if 2) */
GLOBAL(int,ispreambledollars,0); /* displaystyle mode set by $$...$$ */
-GLOBAL(int,isemitcontenttype,1); /* true to emit mime content-type */
GLOBAL(int,fontnum,0); /* cal=1,scr=2,rm=3,it=4,bb=5,bf=6 */
GLOBAL(int,fontsize,NORMALSIZE); /* current size */
GLOBAL(int,displaysize,DISPLAYSIZE); /* use \displaystyle when fontsize>=*/
@@ -716,6 +725,9 @@ GLOBAL(int,fraccenterline,NOVALUE); /* b
/*GLOBAL(int,currentcharclass,NOVALUE);*/ /*primarily to check for PUNCTION*/
GLOBAL(int,iscaching,ISCACHING); /* true if caching images */
GLOBAL(char,cachepath[256],CACHEPATH); /* relative path to cached files */
+GLOBAL(int,isemitcontenttype,1); /* true to emit mime content-type */
+int iscachecontenttype = 0; /* true to cache mime content-type */
+char contenttype[2048] = "\000"; /* content-type:, etc buffer */
GLOBAL(char,pathprefix[256],PATHPREFIX); /*prefix for \input,\counter paths*/
/*GLOBAL(int,iswindows,ISWINDOWS);*/ /* true if compiled for ms windows */
@@ -13474,7 +13486,7 @@ messages
-------------------------------------------------------------------------- */
static char *copyright = /* copyright, gnu/gpl notice */
"+-----------------------------------------------------------------------+\n"
- "|mimeTeX vers 1.64, Copyright(c) 2002-2006, John Forkosh Associates, Inc|\n"
+ "|mimeTeX vers 1.70, Copyright(c) 2002-2008, John Forkosh Associates, Inc|\n"
"+-----------------------------------------------------------------------+\n"
"| mimeTeX is free software, licensed to you under terms of the GNU/GPL, |\n"
"| and comes with absolutely no warranty whatsoever. |\n"
@@ -13551,6 +13563,7 @@ char *gif_outfile = (char *)NULL, /* gif
cachefile[256] = "\000", /* full path and name to cache file*/
*md5str(); /* md5 has of expression */
int maxage = 7200; /* max-age is two hours */
+int valign = (-9999); /*Vertical-Align:baseline-(height-1)*/
/* --- pbm/pgm (-g switch) --- */
int ispbmpgm = 0; /* true to write pbm/pgm file */
int type_pbmpgm(), ptype=0; /* entry point, graphic format */
@@ -13583,7 +13596,18 @@ initialization
/* --- set global variables --- */
msgfp = stdout; /* for comamnd-line mode output */
isss = issupersampling; /* set supersampling flag */
+isemitcontenttype = 1; /* true to emit mime content-type */
+iscachecontenttype = 0; /* true to cache mime content-type */
+*contenttype = '\000'; /* reset content-type:, etc. cache */
+iscaching = ISCACHING; /* true if caching images */
+if ( iscaching ) { /* images are being cached */
+ strcpy(cachepath,CACHEPATH); /* relative path to cached files */
+ if ( *cachepath == '%' ) { /* leading % signals cache headers */
+ iscachecontenttype = 1; /* signal caching mime content-type*/
+ strcpy(cachepath,cachepath+1); } } /* and squeeze out leading % char */
gifSize = 0; /* signal that image not in memory */
+fgred=FGRED; fggreen=FGGREEN; fgblue=FGBLUE; /* default foreground colors */
+bgred=BGRED; bggreen=BGGREEN; bgblue=BGBLUE; /* default background colors */
shrinkfactor = shrinkfactors[NORMALSIZE]; /* set shrinkfactor */
for ( ipattern=1; ipattern<=51; ipattern++ )
patternnumcount0[ipattern] = patternnumcount1[ipattern] = 0;
@@ -13594,6 +13618,9 @@ if ( query != NULL ) /* check query st
if ( strlen(query) >= 1 ) /* caller gave us a query string */
{ strncpy(expression,query,MAXEXPRSZ); /* so use it as expression */
expression[MAXEXPRSZ] = '\000'; /* make sure it's null terminated */
+ if ( 0 ) /*true to remove leading whitespace*/
+ while ( isspace(*expression) && *expression!='\000' )
+ strcpy(expression,expression+1); /* squeeze out white space */
isquery = 1; } /* and set isquery flag */
if ( !isquery ) /* empty query string */
{ char *host = getenv("HTTP_HOST"), /* additional getenv("") results */
@@ -13913,9 +13940,11 @@ if ( isquery ) /* don't cache command
/* --- emit mime content-type line --- */
if ( 0 && isemitcontenttype ) /* now done in emitcache() */
{ fprintf( stdout, "Cache-Control: max-age=%d\n",maxage );
+ if ( abs(valign) < 999 ) /* have vertical align */
+ fprintf( stdout, "Vertical-Align: %d\n",valign );
fprintf( stdout, "Content-type: image/gif\n\n" ); }
/* --- emit cached image if it already exists --- */
- if ( emitcache(cachefile,maxage,0) > 0 ) /* cached image emitted */
+ if ( emitcache(cachefile,maxage,valign,0) > 0 ) /* cached image emitted */
goto end_of_job; /* so nothing else to do */
/* --- log caching request --- */
if ( msglevel >= 1 /* check if logging */
@@ -13958,7 +13987,8 @@ if ( !isdumpimage ) /* don't mix ascii
rasterize expression and put a border around it
-------------------------------------------------------------------------- */
/* --- preprocess expression, converting LaTeX constructs for mimeTeX --- */
-expression = mimeprep(expression); /* preprocess expression */
+if ( expression != NULL ) { /* have expression to rasterize */
+ expression = mimeprep(expression); } /* preprocess expression */
/* --- double-check that we actually have an expression to rasterize --- */
if ( expression == NULL ) /* nothing to rasterize */
{ if ( (!isquery||isqlogging) && msgfp!=NULL ) /*emit error if not a query*/
@@ -13977,6 +14007,9 @@ if ( issupersampling ) /* no border ne
else /* for mime xbitmaps must have... */
bp = border_raster(sp->image,0,0,0,1); /* image width multiple of 8 bits */
sp->image = bitmap_raster = bp; /* global copy for gif,png output */
+if ( sp!=NULL && bp!=NULL ) { /* have raster */
+ valign = sp->baseline - (bp->height - 1); /* #pixels for Vertical-Align: */
+ if ( abs(valign) > 255 ) valign = (-9999); } /* sanity check */
if ( ispbmpgm && ptype<2 ) /* -g switch or -g1 switch */
type_pbmpgm(bp,ptype,pbm_outfile); /* emit b/w pbm file */
/* -------------------------------------------------------------------------
@@ -14119,15 +14152,24 @@ if ( isquery /* called from browser
------------------------------------------------------------------------- */
/* --- don't use memory buffer if outout file given --- */
if ( gif_outfile != NULL ) isinmemory = 0; /* reset memory buffer flag */
+ /* --- construct contenttype[] buffer containing mime headers --- */
+ if ( 1 ) { /* always construct buffer */
+ sprintf( contenttype, "Cache-Control: max-age=%d\n", maxage );
+ /*sprintf(contenttype+strlen(contenttype),
+ "Expires: Fri, 31 Oct 2003 23:59:59 GMT\n" );*/
+ /*sprintf(contenttype+strlen(contenttype),
+ "Last-Modified: Wed, 15 Oct 2003 01:01:01 GMT\n");*/
+ if ( abs(valign) < 999 ) /* have Vertical-Align: header info*/
+ sprintf( contenttype+strlen(contenttype),
+ "Vertical-Align: %d\n", valign );
+ sprintf( contenttype+strlen(contenttype),
+ "Content-type: image/gif\n\n" ); }
/* --- emit mime content-type line --- */
if ( isemitcontenttype /* content-type lines wanted */
&& !isdumpimage /* don't mix ascii with image dump */
&& !isinmemory /* done below if in memory */
&& !iscaching ) /* done by emitcache() if caching */
- { fprintf( stdout, "Cache-Control: max-age=%d\n",maxage );
- /*fprintf( stdout, "Expires: Fri, 31 Oct 2003 23:59:59 GMT\n" );*/
- /*fprintf( stdout, "Last-Modified: Wed, 15 Oct 2003 01:01:01 GMT\n" );*/
- fprintf( stdout, "Content-type: image/gif\n\n" ); }
+ { fputs(contenttype,stdout); } /* emit content-type: header buffer*/
/* --- write output to memory buffer, possibly for testing --- */
if ( isinmemory /* want gif written to memory */
|| isdumpbuffer ) /*or dump memory buffer for testing*/
@@ -14190,9 +14232,9 @@ if ( isquery /* called from browser
|| msglevel >= 99 ) { /* or debugging */
int maxage2 = (isdumpimage?(-1):maxage); /* no headers if dumping image */
if ( iscaching ) /* caching enabled */
- emitcache(cachefile,maxage2,0); /* cached image (hopefully) emitted*/
+ emitcache(cachefile,maxage2,valign,0); /*emit cached image (hopefully)*/
else if ( isinmemory ) /* or emit image from memory buffer*/
- emitcache(gif_buffer,maxage2,1); } /* emitted from memory buffer */
+ emitcache(gif_buffer,maxage2,valign,1); } /*emitted from memory buffer*/
/* --- for testing, may need to write image buffer to file --- */
if ( isdumpbuffer > 99 ) /* gif image in memory buffer */
if ( gifSize > 0 ) /* and it's not an empty buffer */
@@ -14572,14 +14614,16 @@ return ( nlogged ); /* back to caller
} /* --- end-of-function logger() --- */
/* ==========================================================================
- * Function: emitcache ( cachefile, maxage, isbuffer )
+ * Function: emitcache ( cachefile, maxage, valign, isbuffer )
* Purpose: dumps bytes from cachefile to stdout
* --------------------------------------------------------------------------
* Arguments: cachefile (I) pointer to null-terminated char string
* containing full path to file to be dumped,
* or contains buffer of bytes to be dumped
- * maxage (I) int containing maxage. in seconds, for
+ * maxage (I) int containing maxage, in seconds, for
* http header, or -1 to not emit headers
+ * valign (I) int containing Vertical-Align:, in pixels,
+ * for http header, or <= -999 to not emit
* isbuffer (I) 1 if cachefile is buffer of bytes to be
* dumped
* --------------------------------------------------------------------------
@@ -14588,7 +14632,7 @@ return ( nlogged ); /* back to caller
* Notes: o
* ======================================================================= */
/* --- entry point --- */
-int emitcache ( char *cachefile, int maxage, int isbuffer )
+int emitcache ( char *cachefile, int maxage, int valign, int isbuffer )
{
/* -------------------------------------------------------------------------
Allocations and Declarations
@@ -14597,6 +14641,8 @@ int nbytes=gifSize, readcachefile(); /*
FILE *emitptr = stdout; /* emit cachefile to stdout */
unsigned char buffer[MAXGIFSZ+1]; /* bytes from cachefile */
unsigned char *buffptr = buffer; /* ptr to buffer */
+int isvalign = (abs(valign)<999?1:0); /* true to emit Vertical-Align: */
+int iscontenttypecached = iscachecontenttype; /*true if headers cached*/
/* -------------------------------------------------------------------------
initialization
-------------------------------------------------------------------------- */
@@ -14604,17 +14650,21 @@ initialization
if ( emitptr == (FILE *)NULL ) /* failed to open emit file */
goto end_of_job; /* so return 0 bytes to caller */
/* --- read the file if necessary --- */
-if ( isbuffer ) /* cachefile is buffer */
- buffptr = (unsigned char *)cachefile; /* so reset buffer pointer */
-else /* cachefile is file name */
- if ( (nbytes = readcachefile(cachefile,buffer)) /* read the file */
- < 1 ) goto end_of_job; /* quit if file not read */
+if ( isbuffer ) { /* cachefile is buffer */
+ buffptr = (unsigned char *)cachefile; /* so reset buffer pointer */
+ iscontenttypecached = 0; } /* and iscontenttypecached flag */
+else { /* cachefile is file name */
+ if ( (nbytes = readcachefile(cachefile,buffer)) /* read the file */
+ < 1 ) goto end_of_job; } /* quit if file not read */
/* --- first emit http headers if requested --- */
if ( isemitcontenttype /* content-type lines enabled */
+&& !iscontenttypecached /* and not in cached image */
&& maxage >= 0 ) /* caller wants http headers */
{ /* --- emit mime content-type line --- */
fprintf( emitptr, "Cache-Control: max-age=%d\n",maxage );
fprintf( emitptr, "Content-Length: %d\n",nbytes );
+ if ( isvalign ) /* Vertical-Align: header wanted */
+ fprintf( emitptr, "Vertical-Align: %d\n",valign );
fprintf( emitptr, "Content-type: image/gif\n\n" ); }
/* -------------------------------------------------------------------------
set stdout to binary mode (for Windows)