chimera2/chimera/view.c

332 lines
6.5 KiB
C

/*
* view.c
*
* Copyright (c) 1995-1997, John Kilburg <john@cs.unlv.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "port_before.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Paned.h>
#include "port_after.h"
#include "TextField.h"
#include "ChimeraP.h"
typedef struct
{
MemPool mp;
ChimeraSink wp;
char *command;
ChimeraTask wt;
ChimeraResources cres;
Widget pop, message;
} ViewInfo;
static char *ViewFind _ArgProto((MemPool, char *, char *));
static void ViewDestroy _ArgProto((ViewInfo *));
static int ViewSinkInit _ArgProto((ChimeraSink, void *));
static void ViewSinkAdd _ArgProto((void *));
static void ViewSinkEnd _ArgProto((void *));
static void ViewSinkMessage _ArgProto((void *, char *));
static void ViewMakePop _ArgProto((ViewInfo *));
static void ViewDialogStop _ArgProto((Widget, XtPointer, XtPointer));
/*
* ViewFind
*
* Return a command string for a type.
*/
static char *
ViewFind(mp, filelist, content)
MemPool mp;
char *filelist;
char *content;
{
FILE *fp;
char *f;
char buffer[BUFSIZ];
char ctype[BUFSIZ];
char command[BUFSIZ];
char junk[BUFSIZ];
char *filename;
MemPool tmp;
tmp = MPCreate();
f = filelist;
while ((filename = mystrtok(f, ':', &f)) != NULL)
{
filename = FixPath(mp, filename);
if (filename == NULL) continue;
fp = fopen(filename, "r");
if (fp == NULL) continue;
while (fgets(buffer, sizeof(buffer), fp))
{
if (buffer[0] == '#' || buffer[0] == '\n') continue;
if (sscanf(buffer, "%[^;]%[;]%[^;\n]", ctype, junk, command) == 3)
{
if (RequestMatchContent(tmp, ctype, content))
{
fclose(fp);
MPDestroy(tmp);
return(MPStrDup(mp, command));
}
}
}
fclose(fp);
}
MPDestroy(tmp);
return(NULL);
}
static void
ViewSinkEnd(closure)
void *closure;
{
ViewInfo *vi = (ViewInfo *)closure;
char *filename;
FILE *fp;
char *final;
char *path;
byte *data;
size_t len;
MIMEHeader mh;
size_t finallen;
SinkGetData(vi->wp, &data, &len, &mh);
if (data == NULL || len == 0)
{
ViewDestroy(vi);
return;
}
filename = mytmpnam(vi->mp);
if ((fp = fopen(filename, "w")) != NULL)
{
fwrite(data, len, 1, fp);
fclose(fp);
if ((path = ResourceGetString(vi->cres, "view.path")) == NULL)
{
if ((path = getenv("PATH")) == NULL) path = "";
}
finallen = strlen(" ; rm &") + strlen(path) + strlen(filename) * 2 +
strlen(vi->command) + strlen("PATH=") + 1;
final = (char *)MPGet(vi->mp, finallen);
strcpy(final, "(PATH=");
strcat(final, path);
strcat(final, " ");
sprintf (final + strlen(final), vi->command, filename);
strcat(final, "; rm ");
strcat(final, filename);
strcat(final, ") &");
system(final);
}
ViewDestroy(vi);
return;
}
/*
* ViewSinkMessage
*/
void
ViewSinkMessage(closure, message)
void *closure;
char *message;
{
ViewInfo *vi = (ViewInfo *)closure;
TextFieldSetString(vi->message, message);
return;
}
/*
* ViewDestroy
*/
static void
ViewDestroy(vi)
ViewInfo *vi;
{
ChimeraResources cres = vi->cres;
if (vi->pop != NULL) XtDestroyWidget(vi->pop);
SinkDestroy(vi->wp);
MPDestroy(vi->mp);
ChimeraRemoveReference(cres);
return;
}
/*
* ViewSinkAdd
*/
void
ViewSinkAdd(closure)
void *closure;
{
return;
}
/*
* ViewSinkInit
*/
static int
ViewSinkInit(wp, closure)
ChimeraSink wp;
void *closure;
{
char *url;
char *caplist;
ViewInfo *vi = (ViewInfo *)closure;
ChimeraRequest *wr;
if ((caplist = ResourceGetString(vi->cres, "view.capFiles")) == NULL)
{
caplist = "~/.mailcap";
}
if ((vi->command = ViewFind(vi->mp, caplist,
SinkGetInfo(wp, "content-type"))) == NULL)
{
url = SinkGetInfo(wp, "x-url");
if ((wr = RequestCreate(vi->cres, url, NULL)) == NULL) return(-1);
DownloadOpen(vi->cres, wr);
ViewDestroy(vi);
return(-1);
}
return(0);
}
static void
ViewDialogStop(w, cldata, cbdata)
Widget w;
XtPointer cldata, cbdata;
{
ViewDestroy((ViewInfo *)cldata);
return;
}
static void
ViewMakePop(vi)
ViewInfo *vi;
{
Window rw, cw;
int rx, ry, wx, wy;
unsigned int mask;
Widget paned;
Widget box;
Widget stop;
XQueryPointer(vi->cres->dpy, DefaultRootWindow(vi->cres->dpy),
&rw, &cw,
&rx, &ry,
&wx, &wy,
&mask);
vi->pop = XtVaAppCreateShell("view", "View",
transientShellWidgetClass, vi->cres->dpy,
XtNx, rx - 2,
XtNy, ry - 2,
NULL);
paned = XtCreateManagedWidget("paned",
panedWidgetClass, vi->pop,
NULL, 0);
box = XtCreateManagedWidget("box", boxWidgetClass, paned, NULL, 0);
vi->message = XtVaCreateManagedWidget("message",
textfieldWidgetClass, box,
NULL);
box = XtCreateManagedWidget("box2", boxWidgetClass, paned, NULL, 0);
stop = XtVaCreateManagedWidget("stop", commandWidgetClass, box, NULL, 0);
XtAddCallback(stop, XtNcallback, ViewDialogStop, vi);
XtRealizeWidget(vi->pop);
return;
}
/*
* ViewOpen
*/
void
ViewOpen(cres, wr)
ChimeraResources cres;
ChimeraRequest *wr;
{
ViewInfo *vi;
ChimeraSinkHooks hooks;
MemPool mp;
myassert(wr != NULL, "Request cannot be NULL.");
mp = MPCreate();
vi = (ViewInfo *)MPCGet(mp, sizeof(ViewInfo));
vi->mp = mp;
vi->cres = cres;
memset(&hooks, 0, sizeof(hooks));
hooks.init = ViewSinkInit;
hooks.add = ViewSinkAdd;
hooks.end = ViewSinkEnd;
hooks.message = ViewSinkMessage;
if ((vi->wp = SinkCreate(cres, wr)) == NULL) MPDestroy(mp);
else
{
SinkSetHooks(vi->wp, &hooks, vi);
ViewMakePop(vi);
ChimeraAddReference(vi->cres);
}
return;
}