/*****************************************************************************/
/*
                                   charset.c

CGI-compliant script to render the ISO Latin 1 character set using HTML
entities.


BUILD
-----
See BUILD_CHARSET.COM


VERSION HISTORY
---------------
23-DEC-2003  MGD  v1.2.1, minor conditional mods to support IA64
04-OCT-1998  MGD  v1.2.0, provide content-type "; charset=...",
                        and some further functionality
20-MAY-1998  MGD  v1.1.0, cosmetic changes
07-MAR-1996  MGD  v1.0.0, quick hack
*/
/*****************************************************************************/

#define SOFTWAREVN "1.2.1"
#define SOFTWARENM "CHARSET"
#ifdef __ALPHA
   char SoftwareID [] = SOFTWARENM " AXP-" SOFTWAREVN;
#endif
#ifdef __ia64
   char SoftwareID [] = SOFTWARENM " IA64-" SOFTWAREVN;
#endif
#ifdef __VAX
   char SoftwareID [] = SOFTWARENM " VAX-" SOFTWAREVN;
#endif

#include <stdio.h>
#include <errno.h>

#define boolean int
#define true 1
#define false 0
 
/* macro provides NULL pointer if CGI variable does not exist */
#define GetCgiVarIfExists(CharPointer,CgiVariableName) \
   CharPointer = getenv(CgiVariableName)

/* macro provides pointer to empty string even if CGI variable does not exist */
#define GetCgiVar(CharPointer,CgiVariableName) \
   if ((CharPointer = getenv(CgiVariableName)) == NULL) \
       CharPointer = "";

#define DEFAULT_CHARSET "ISO-8859-1"

char  *CharsetList [] = {
"iso-8859-1", "iso-8859-1 (Latin-1, West European)",
"iso-8859-2", "iso-8859-2 (Latin-2, East European)",
"iso-8859-3", "iso-8859-3 (Latin-3, South European)",
"iso-8859-4", "iso-8859-4 (Latin-4, North European)",
"iso-8859-5", "iso-8859-5 (Latin/Cyrillic)",
"iso-8859-6", "iso-8859-6 (Latin/Arabic)",
"iso-8859-7", "iso-8859-7 (Latin/Greek)",
"iso-8859-8", "iso-8859-8 (Latin-5, Hebrew)",
"iso-8859-9", "iso-8859-9 (Latin-6, Turkish)",
"iso-8859-10", "iso-8859-10 (Latin-6, Nordic)",
"utf-8", "utf-8 (Unicode)",
"koi8-r", "koi8-r (Russian Cyrillic)",
"koi8", "koi8 (Non-Russian Cyrillic)",
"windows-1251", "windows-1251 (Cyrillic)",
"" };

char  Utility [] = "CHARSET";

/*****************************************************************************/
/*
*/

main ()

{
   int  Count,
        EndCount,
        Page,
        OptionSelected,
        StartCount;
   char  CountChar;
   char  *CgiFormFontNamePtr,
         *CgiFormFontListPtr,
         *CgiFormPagePtr,
         *CgiHttpUserAgentPtr,
         *CgiQueryStringPtr,
         *CgiScriptNamePtr,
         *CgiServerSoftwarePtr,
         *CharsetPtr;
   char  ContentTypeCharset [128],
         UsingCharset [256];
      
   /*********/
   /* begin */
   /*********/

   /* reopen output stream so that the '\r' and '\n' are not filtered */
#ifdef __DECC
   if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL)
      exit (vaxc$errno);
#else
   if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "rfm=udf")) == NULL)
      exit (vaxc$errno);
#endif

   GetCgiVar (CgiServerSoftwarePtr, "WWW_SERVER_SOFTWARE");
   if (!CgiServerSoftwarePtr[0]) CgiServerSoftwarePtr = SoftwareID;

   GetCgiVar (CgiHttpUserAgentPtr, "WWW_HTTP_USER_AGENT");
   if (!CgiHttpUserAgentPtr[0]) CgiHttpUserAgentPtr = "<I>unknown browser!</I>";

   GetCgiVar (CgiScriptNamePtr, "WWW_SCRIPT_NAME");
   GetCgiVar (CgiQueryStringPtr, "WWW_QUERY_STRING");
   GetCgiVar (CgiFormFontNamePtr, "WWW_FORM_FONTNAME");
   GetCgiVar (CgiFormFontListPtr, "WWW_FORM_FONTLIST");
   GetCgiVar (CgiFormPagePtr, "WWW_FORM_PAGE");
   Page = atol(CgiFormPagePtr);

   CharsetPtr = NULL;

   if (CgiFormFontNamePtr[0])
      CharsetPtr = CgiFormFontNamePtr;
   else
   if (CgiFormFontListPtr[0])
      CharsetPtr = CgiFormFontListPtr;
   else
   if (!CgiFormPagePtr[0] && CgiQueryStringPtr[0])
      CharsetPtr = CgiQueryStringPtr;
   else
      CharsetPtr = getenv ("CHARSET_DEFAULT");

   if (CharsetPtr == NULL)
   {
      GetCgiVar (CharsetPtr, "WWW_REQUEST_CHARSET");
      if (!CharsetPtr[0]) GetCgiVar (CharsetPtr, "WWW_SERVER_CHARSET");
      if (!CharsetPtr[0]) CharsetPtr = DEFAULT_CHARSET;
   }
   if (CharsetPtr[0])
      sprintf (ContentTypeCharset, "; charset=%s", CharsetPtr);
   else
      ContentTypeCharset[0] = '\0';

   if (CharsetPtr[0])
      sprintf (UsingCharset, "<BR>using character set &quot;%s&quot\n",
               CharsetPtr);
   else
      UsingCharset[0] = '\0';

   StartCount = Page * 256;
   EndCount = Page * 256 + 255;

   fprintf (stdout,
"HTTP/1.0 200 Success\r\n\
Server: %s\r\n\
Content-Type: text/html%s\r\n\
\r\n\
<HTML>\n\
<HEAD>\n\
<META NAME=\"generator\" CONTENT=\"%s\">\n\
<TITLE>Charset</TITLE>\n\
</HEAD>\n\
<BODY BGCOLOR=\"#ffffff\" TEXT=\"#000000\">\n\
<TABLE BORDER=0 CELLSPACING=2 CELLPADDING=2>\n\
<TR><TH COLSPAN=16>\n\
%s\n\
%s\
<BR>renders the entity set %d to %d in the way you see below\n\
</TH><TR>\n\
<TD HEIGHT=5></TD></TR>\n\
<TR>\n\
<TD></TD><TD></TD>\n",
      CgiServerSoftwarePtr, ContentTypeCharset, SoftwareID,
      CgiHttpUserAgentPtr, UsingCharset, StartCount, EndCount);

   for (Count = StartCount; Count <= EndCount; Count++)
   {
      if (!(Count % 8))
      {
         if (Count > 1) fprintf (stdout, "</TR>\n");
         fprintf (stdout, "<TR>\n");
      }
      fprintf (stdout,
"<TD ALIGN=right><TT>&amp;#%d;</TT></TD>\
<TD ALIGN=left>&#%d;</TD>\n",
         Count, Count);
   }

   fprintf (stdout,
"</TR>\n\
<TR><TD HEIGHT=5></TD></TR>\n\
</TABLE>\n\
<B>To use a specific character set add it as a query string.\n\
<BR>For example &nbsp;...&nbsp; &quot;%s?ISO-8859-5&quot;\n\
<P>Alternatively, select via the following form.</B>\n\
<BR><FORM ACTION=%s>\n\
<SELECT NAME=fontlist>\n",
     CgiScriptNamePtr, CgiScriptNamePtr);

   Count = OptionSelected = 0;
   while (CharsetList[Count][0])
   {
      if (strsame (CharsetPtr, CharsetList[Count], -1))
      {
         fprintf (stdout, "<OPTION SELECTED VALUE=\"%s\">%s\n",
                  CharsetList[Count], CharsetList[Count+1]);
         OptionSelected = Count;
      }
      else
         fprintf (stdout, "<OPTION VALUE=\"%s\">%s\n",
                  CharsetList[Count], CharsetList[Count+1]);
      Count += 2;
   }

   if (!OptionSelected)
      fprintf (stdout, "<OPTION SELECTED VALUE=\"%s\">%s\n",
               CharsetPtr, CharsetPtr);

   fprintf (stdout,
"</SELECT>\n\
&nbsp;or enter name &nbsp;...&nbsp;\n\
<INPUT TYPE=text SIZE=15 NAME=fontname>\n\
<BR><INPUT TYPE=submit VALUE=\" Display \">\n\
<INPUT TYPE=reset VALUE=\" Reset \">\n\
</FORM>\n\
</BODY>\n\
</HTML>\n");

   exit (1);
}

/****************************************************************************/
/*
Does a case-insensitive, character-by-character string compare and returns 
true if two strings are the same, or false if not.  If a maximum number of 
characters are specified only those will be compared, if the entire strings 
should be compared then specify the number of characters as 0.
*/ 

boolean strsame
(
register char *sptr1,
register char *sptr2,
register int  count
)
{
   while (*sptr1 && *sptr2)
   {
      if (toupper (*sptr1++) != toupper (*sptr2++)) return (false);
      if (count)
         if (!--count) return (true);
   }
   if (*sptr1 || *sptr2)
      return (false);
   else
      return (true);
}

/*****************************************************************************/

