home *** CD-ROM | disk | FTP | other *** search
- /*
- * update.c : Handles the bitmaps and runs the update command.
- * This maintains caches of bitmaps and widgets to
- * avoid calls to XReadBitmapFromFile() and
- * XtCreateManagedWidget() on every update.
- *
- * George Ferguson, ferguson@cs.rochester.edu, 15 Jul 1990.
- *
- * $Id: update.c,v 1.5 90/08/21 11:36:56 ferguson Exp $
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/param.h>
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Xaw/Toggle.h>
- #include <X11/Xaw/Cardinals.h>
- #include "app-resources.h"
- #include "xmon.h"
-
- /*
- * Functions defined
- */
- void initMemory(),clearBitmapCache(),updateFaces();
- char *getTextFromWidget();
- static void openNameCommand(),convertNameToFile(),closeNameCommand();
- static Pixmap lookupBitmap();
-
- /*
- * The widget cache:
- */
- typedef struct _CachedWidgetRec {
- char *text;
- Widget widget;
- struct _CachedWidgetRec *next;
- } CachedWidgetRec;
- static CachedWidgetRec *widgetRecs;
-
- /*
- * The pixmap cache:
- */
- typedef struct _CachedBitmapRec {
- char *user;
- Pixmap pixmap;
- struct _CachedBitmapRec *next;
- } CachedBitmapRec;
- static CachedBitmapRec *bitmapRecs;
-
- /* - - - - - - - - */
-
- void
- initMemory()
- {
- widgetRecs = NULL;
- radioGroup = NULL;
- bitmapRecs = NULL;
- }
-
- void
- clearBitmapCache()
- {
- CachedBitmapRec *p,*q;
-
- p = bitmapRecs;
- while (p != NULL) {
- q = p->next;
- XFreePixmap(XtDisplay(toplevel),p->pixmap);
- XtFree(p->user);
- XtFree(p);
- p = q;
- }
- bitmapRecs = NULL;
- }
-
- /* - - - - - - - - */
- /*
- * updateFaces() : Redraw the face widgets.
- */
- void
- updateFaces()
- {
- Arg args[2];
- FILE *fp;
- CachedWidgetRec *p,*q;
- char buf[256],user[256];
- int i;
-
- XDefineCursor(XtDisplay(toplevel),XtWindow(toplevel),
- appResources.updateCursor);
- XFlush(XtDisplay(toplevel));
- if (appResources.debug)
- printf("updateCommand: \"%s\"\n",appResources.updateCommand);
- fp = popen(appResources.updateCommand,"r");
- if (fp == NULL) {
- fprintf(stderr,"%s: couldn't execute updateCommand \"%s\"\n",
- program,appResources.updateCommand);
- XUndefineCursor(XtDisplay(toplevel),XtWindow(toplevel));
- return;
- }
- p = widgetRecs;
- q = NULL;
- if (radioGroup != NULL)
- XawToggleUnsetCurrent(radioGroup);
- openNameCommand();
- while (!feof(fp)) {
- if (fgets(buf,256,fp) == 0)
- break;
- if (buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = '\0';
- else {
- fprintf(stderr,"%s: line too long: %s...\n",program,buf);
- while (!feof(fp) && fgetc(fp) != '\n') ;
- }
- i = 0;
- for (i=0; i < 255 && buf[i] && !isspace(buf[i]); i++)
- user[i] = buf[i];
- user[i] = '\0';
- if (p == NULL) {
- if (q == NULL)
- p = widgetRecs = XtNew(CachedWidgetRec);
- else
- p = q->next = XtNew(CachedWidgetRec);
- p->next = NULL;
- p->text = NULL;
- XtSetArg(args[0],XtNmappedWhenManaged,False);
- p->widget = XtCreateManagedWidget("face",toggleWidgetClass,
- faceBox,args,ONE);
- if (radioGroup == NULL)
- radioGroup = p->widget;
- XtSetArg(args[0],XtNradioData,p->widget);
- XtSetValues(p->widget,args,ONE); /* set XawToggleGetCurrent info*/
- XawToggleChangeRadioGroup(p->widget,radioGroup);
- }
- XtSetArg(args[0],XtNbitmap,lookupBitmap(user));
- XtSetValues(p->widget,args,ONE); /* set bitmap */
- XtFree(p->text);
- p->text = XtNewString(buf);
- XtMapWidget(p->widget);
- q = p;
- p = p->next;
- }
- closeNameCommand();
- pclose(fp);
- while (p != NULL) { /* unmap leftover widgets */
- XtUnmapWidget(p->widget);
- p = p->next;
- }
- XUndefineCursor(XtDisplay(toplevel),XtWindow(toplevel));
- XFlush(XtDisplay(toplevel));
- }
-
- /* - - - - - - - - */
- /* These functions map "user" names from the updateCommand into icon
- * names using the nameCommand. We ignore the potential deadlock if 4K
- * get into the pipes; it shouldn't happen with newline buffering.
- */
-
- static FILE *writeFp,*readFp;
-
- static void
- openNameCommand()
- {
- int fd[4],pid;
-
- if (appResources.nameCommand == NULL) {
- writeFp = readFp = NULL;
- return;
- }
- if (appResources.debug)
- printf("nameCommand: \"%s\"\n",appResources.nameCommand);
- if (pipe(fd) < 0 || pipe(fd+2) < 0) {
- fprintf(stderr,"%s: couldn't create pipes for nameCommand \"%s\"\n",
- program,appResources.nameCommand);
- writeFp = readFp = NULL;
- return;
- }
- if ((pid=fork()) < 0) { /* error */
- fprintf(stderr,"%s: couldn't fork nameCommand \"%s\"\n",program,
- appResources.nameCommand);
- writeFp = readFp = NULL;
- return;
- } else if (pid == 0) { /* child */
- dup2(fd[0],0);
- close(fd[1]);
- close(fd[2]);
- dup2(fd[3],1);
- execlp(appResources.nameCommand,appResources.nameCommand,NULL);
- fprintf(stderr,"%s: couldn't exec nameCommand \"%s\"\n",program,
- appResources.nameCommand);
- exit(-1);
- } else { /* parent */
- close(fd[0]);
- writeFp = fdopen(fd[1],"w");
- readFp = fdopen(fd[2],"r");
- close(fd[3]);
- if (writeFp == NULL || readFp == NULL) {
- fprintf(stderr,"%s: couldn't open pipes for nameCommand \"%s\"\n",
- program,appResources.nameCommand);
- writeFp = readFp = NULL;
- }
- }
- }
-
- static void
- convertNameToFile(user,icon,len)
- char user[],icon[];
- int len;
- {
- char *strrchr();
-
- if (writeFp == NULL) {
- strncpy(icon,user,len);
- return;
- }
- fputs(user,writeFp);
- fputs("\n",writeFp);
- fflush(writeFp);
- fgets(icon,len,readFp);
- if (strrchr(icon,'\n') != NULL)
- *(strrchr(icon,'\n')) = '\0'; /* eat \n */
- }
-
- static void
- closeNameCommand()
- {
- if (writeFp == NULL)
- return;
- fclose(writeFp);
- fclose(readFp);
- wait(NULL);
- }
-
- /* - - - - - - - - */
- /* Bitmap cache to avoid doing "XReadBitmapFromFile" on every update.
- * Have to read file into a bitmap then copy to pixmap. Blech.
- */
-
- static filename[MAXPATHLEN];
-
- static Pixmap
- lookupBitmap(user)
- char user[];
- {
- CachedBitmapRec *p,*q;
- char icon[256];
- unsigned int w,h,d;
- int x,y,flag;
- Pixmap bitmap;
- XCharStruct ch;
-
- for (p=bitmapRecs, q=NULL; p != NULL; q=p, p=p->next)/* check the cache */
- if (strcmp(p->user,user) == 0) /* hit */
- return(p->pixmap); /* so return it */
- if (q == NULL) { /* else new one */
- bitmapRecs = XtNew(CachedBitmapRec); /* this is first */
- q = bitmapRecs;
- } else {
- q->next = XtNew(CachedBitmapRec); /* else add to end */
- q = q->next;
- }
- q->next = NULL;
- q->user = XtNewString(user);
- flag = appResources.addNames; /* definitely add name? */
- convertNameToFile(user,icon,255); /* map to icon name */
- strcpy(filename,appResources.faceDirectory);
- strcat(filename,"/");
- strncat(filename,icon,255-strlen(filename));
- if (XReadBitmapFile(XtDisplay(toplevel),XtWindow(toplevel),filename,
- &w,&h,&bitmap,&x,&y) != BitmapSuccess) {
- strcpy(filename,appResources.faceDirectory);
- strcat(filename,"/nobody");
- if (XReadBitmapFile(XtDisplay(toplevel),XtWindow(toplevel),filename,
- &w,&h,&bitmap,&x,&y) != BitmapSuccess)
- fail("couldn't open default bitmap \"%s\"\n",filename);
- flag = 1; /* always add name to default icon */
- }
- q->pixmap = XCreatePixmap(XtDisplay(toplevel),XtWindow(toplevel),w,h,
- PlanesOfScreen(XtScreen(toplevel)));
- XCopyPlane(XtDisplay(toplevel),bitmap,q->pixmap,gc,0,0,w,h,0,0,1);
- XFreePixmap(XtDisplay(toplevel),bitmap);
- if (flag) {
- XTextExtents(XQueryFont(XtDisplay(toplevel),appResources.smallFont),
- user,strlen(user),&d,&x,&y,&ch);
- x = ((int)w - ch.width)/2;
- if (x < 1) x = 1;
- y = h - 2;
- if (appResources.opaqueNames)
- XDrawImageString(XtDisplay(toplevel),q->pixmap,gc,x,y,user,
- strlen(user));
- else
- XDrawString(XtDisplay(toplevel),q->pixmap,gc,x,y,user,strlen(user));
- }
- return(q->pixmap);
- }
-
- /* - - - - - - - - */
- /*
- * getTextFromWidget() : Return the text stored with the widget.
- */
- char *
- getTextFromWidget(w)
- Widget w;
- {
- CachedWidgetRec *p;
-
- if (w == NULL)
- return(NULL);
- p = widgetRecs;
- while (p != NULL) {
- if (p->widget == w)
- return(p->text);
- else
- p = p->next;
- }
- return(NULL);
- }
-