/* Copyright (c) 1994.  All rights reserved. */
/* Written from scratch July 30, 1994, by A. P. Smith. */
/* Open up the ~/.mime-types and ~/.mailcap files to check what
   viewers to try to call on a new file (if they don't exist look for
   MIMELIBDIR/mime.types and MAILCAPLIBDIR/mailcap). */

#include "config.h"
#if defined(HTEX) || defined(XHDVI)

#include <kpathsea/c-ctype.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/variable.h>

#ifndef MIMELIBDIR
#define MIMELIBDIR "/usr/local/etc"
#endif
#ifndef MAILCAPLIBDIR
#define MAILCAPLIBDIR "/usr/local/etc"
#endif


typedef struct _mimemap {
	char *content_type;
	char *extensions;
} Mimemap;

Mimemap mime_defaults[] = {
{ "application/octet-stream",    "bin", },
{ "application/oda",             "oda", },
{ "application/pdf",             "pdf", },
{ "application/postscript",      "ai eps epsf ps", },
{ "application/rtf",             "rtf", },
{ "application/x-mif",           "mif", },
{ "application/x-csh",           "csh", },
{ "application/x-dvi",           "dvi", },
{ "application/x-hdf",           "hdf", },
{ "application/x-latex",         "latex", },
{ "application/x-netcdf",        "nc cdf", },
{ "application/x-sh",            "sh", },
{ "application/x-tcl",           "tcl", },
{ "application/x-tex",           "tex", },
{ "application/x-texinfo",       "texinfo texi", },
{ "application/x-troff",         "t tr roff", },
{ "application/x-troff-man",     "man", },
{ "application/x-troff-me",      "me", },
{ "application/x-troff-ms",      "ms", },
{ "application/x-wais-source",   "src", },
{ "application/zip",             "zip", },
{ "application/x-bcpio",         "bcpio", },
{ "application/x-cpio",          "cpio", },
{ "application/x-gtar",          "gtar", },
{ "application/x-shar",          "shar", },
{ "application/x-sv4cpio",       "sv4cpio", },
{ "application/x-sv4crc",        "sv4crc", },
{ "application/x-tar",           "tar", },
{ "application/x-ustar",         "ustar", },
{ "audio/basic",                 "au snd", },
{ "audio/x-aiff",                "aif aiff aifc", },
{ "audio/x-wav",                 "wav", },
{ "image/gif",                   "gif", },
{ "image/ief",                   "ief", },
{ "image/jpeg",                  "jpeg jpg jpe", },
{ "image/tiff",                  "tiff tif", },
{ "image/x-cmu-raster",          "ras", },
{ "image/x-portable-anymap",     "pnm", },
{ "image/x-portable-bitmap",     "pbm", },
{ "image/x-portable-graymap",    "pgm", },
{ "image/x-portable-pixmap",     "ppm", },
{ "image/x-rgb",                 "rgb", },
{ "image/x-xbitmap",             "xbm", },
{ "image/x-xpixmap",             "xpm", },
{ "image/x-xwindowdump",         "xwd", },
{ "text/html",                   "html htm", },
{ "text/plain",                  "txt", },
{ "text/richtext",               "rtx", },
{ "text/tab-separated-values",   "tsv", },
{ "text/x-setext",               "etx", },
{ "video/mpeg",                  "mpeg mpg mpe", },
{ "video/quicktime",             "qt mov", },
{ "video/x-msvideo",             "avi", },
{ "video/x-sgi-movie",           "movie", },
};

Mimemap *curmimemap = mime_defaults;
int nmime, maxnmime = 0;

typedef struct _mailcap {
	char *content_type;
	char *viewer;
	Boolean needs_base;
} Mailcap;

Mailcap mailcap_defaults[] = {
{ "audio/*",                    "showaudio %s", False, },
{ "image/*",                    "xv %s", False, },
{ "video/mpeg",                 "mpeg_play %s", False, },
{ "application/pdf",            "acroread %s", False, },
{ "application/postscript",     "ghostview %s", False, },
{ "application/x-dvi",          "xdvi -base %s %s", True, },
};

Mailcap *curmailcap = mailcap_defaults;
int nmailcap, maxnmailcap = 0;

#define LINE 1024
#define MIMESTEP 50

int
parsemimes ()
{
	int i;
	char buf[LINE], *cp, *cp2;
	FILE *strm;
	static int already_called = 0;

	if (already_called) return 1;
	already_called = 1;
	sprintf(buf, "%s/.mime-types", getenv("HOME"));
	if ((strm = xfopen_local(buf, FOPEN_R_MODE)) == NULL) {
	  string mimelibdir = kpse_var_value ("MIMELIBDIR");
	  if (!mimelibdir)
	    mimelibdir = MIMELIBDIR;
	  sprintf(buf, "%s/mime.types", mimelibdir);
	  if ((strm = xfopen_local(buf, FOPEN_R_MODE)) == NULL) {
	          nmime = sizeof(mime_defaults)/sizeof(Mimemap);
	          return 0;
	  }
	}
	curmimemap = (Mimemap *) xmalloc(MIMESTEP*sizeof(Mimemap), "mime");
	maxnmime = MIMESTEP;
	for (i=0; i < maxnmime; i++) {
		curmimemap[i].content_type = curmimemap[i].extensions = NULL;
	}
	nmime = 0;
	while (fgets(buf, LINE, strm) != NULL) {
		cp = buf;
		while (isspace(*cp)) cp++;
		if (*cp == '#') continue;
		if ((cp2 = strchr(cp, ' ')) == NULL)
			if ((cp2 = strchr(cp, '\t')) == NULL) continue;
		*cp2 = '\0'; /* Terminate cp string */
		cp2++;
		while (isspace(*cp2)) cp2++;
		if (*cp2 == '\0') continue; /* No extensions list */
		if (nmime >= maxnmime) {
			maxnmime += MIMESTEP;
			curmimemap = (Mimemap *) realloc(curmimemap,
						maxnmime*sizeof(Mimemap));
			for (i=nmime; i < maxnmime; i++) {
				curmimemap[i].content_type =
				    curmimemap[i].extensions = NULL;
			}
		}
		MyStrAllocCopy(&(curmimemap[nmime].content_type), cp);
		MyStrAllocCopy(&(curmimemap[nmime].extensions), cp2);
		nmime++;
	}
	return 1;
}

int
parsemailcap()
{
	int i;
	char buf[LINE], *cp, *cp2;
	FILE *strm;
	static int already_called = 0;

	if (already_called) return 1;
	already_called = 1;
	sprintf(buf, "%s/.mailcap", getenv("HOME"));
	if ((strm = xfopen_local(buf, FOPEN_R_MODE)) == NULL) {
          string mailcaplibdir = kpse_var_value ("MAILCAPLIBDIR");
	  if (!mailcaplibdir)
            mailcaplibdir = MAILCAPLIBDIR;
          sprintf(buf, "%s/mailcap", MAILCAPLIBDIR);
          if ((strm = xfopen_local(buf, FOPEN_R_MODE)) == NULL) {
                  nmailcap = sizeof(mailcap_defaults)/sizeof(Mailcap);
                  return 0;
          }
	}
	curmailcap = (Mailcap *) malloc(MIMESTEP*sizeof(Mailcap));
	maxnmailcap = MIMESTEP;
	for (i=0; i < maxnmailcap; i++) {
		curmailcap[i].content_type = curmailcap[i].viewer = NULL;
	}
	nmailcap = 0;
	while (fgets(buf, LINE, strm) != NULL) {
		cp = strrchr(buf, '\n');
		if (cp != NULL) *cp = '\0'; /* Get rid of trailing \n */
		cp = buf;
		while (isspace(*cp)) cp++;
		if (*cp == '#') continue;
		if ((cp2 = strchr(cp, ';')) == NULL) continue;
		*cp2 = '\0'; /* Terminate cp string */
		cp2++;
		while (isspace(*cp2)) cp2++;
		if (*cp2 == '\0') continue; /* No viewer info? */
		if (nmailcap >= maxnmailcap) {
			maxnmailcap += MIMESTEP;
			curmailcap = (Mailcap *) realloc(curmailcap,
						maxnmailcap*sizeof(Mailcap));
			for (i=nmailcap; i < maxnmailcap; i++) {
				curmailcap[i].content_type =
				    curmailcap[i].viewer = NULL;
			}
		}
		MyStrAllocCopy(&(curmailcap[nmailcap].content_type), cp);
		MyStrAllocCopy(&(curmailcap[nmailcap].viewer), cp2);
		curmailcap[nmailcap].needs_base = False;
		if ((cp = strstr(curmailcap[nmailcap].viewer, "%s")) == NULL)
				continue; /* Not valid viewer info? */
		if (strstr(cp+2, "%s") != NULL) /* Needs two strings */
			curmailcap[nmailcap].needs_base = True;
		nmailcap++;
	}
	return 0;
}

int
invokeviewer(filename)
   char *filename;
{
	int i;
	char *extension, *cp;
	char *content_type = NULL;
	char *viewer = NULL;
	char viewingcommand[LINE];

	/* First check for the mailcap and mime files */
	(void) parsemimes();
	(void) parsemailcap();
	/* See if filename extension is on the mime list: */
	extension = strrchr(filename,'.');
	if (extension == NULL) return 0;
	extension++;
	for (i=0; i < nmime; i++) { /* Compare with space sep. list of exts */
		cp = curmimemap[i].extensions;
		while ((cp = strstr(cp, extension)) != NULL) {
			if ((cp - curmimemap[i].extensions > 0) &&
				 (cp[-1] != ' ')) {
					cp ++;
					continue;
			}
			cp += strlen(extension);
			if ((*cp != ' ') && (*cp != '\0')) continue;
			content_type = curmimemap[i].content_type;
			break;
		}
		if (content_type != NULL) break;
	}
	if (content_type == NULL) return 0; /* no such mime extension */
	for (i=0; i < nmailcap; i++) {
		if (!strcmp(curmailcap[i].content_type, content_type)) {
			viewer = curmailcap[i].viewer;
			break;
		}
	}
	if (viewer == NULL) return 0;
	/* Turn the (possibly URL) filename into a local file */
	i = fetch_relative_url(URLbase, filename, temporary_dir);
	if (i < 0) return 0;
	wait_for_urls();
	if (curmailcap[i].needs_base) {
		sprintf(viewingcommand, viewer,
			 (URLbase == NULL)? "none":filelist[i].url, filelist[i].file);
	} else {
		sprintf(viewingcommand, viewer, filelist[i].file);
	}
	strcat(viewingcommand, " &");
	if (debug & DBG_HYPER) {
		fprintf(stderr, "Executing: %s\n", viewingcommand);
	}
	system(viewingcommand);
	return 1;
}
#endif /* HTEX || XHDVI */
