#ident "%W%" %G% /* *H * Title cmprss5 * This is a modified version of "imager" * It is intended to give access to buttons and text widgets * without opening an image window *h *C * Picker International, Inc. Ohio Imaging Nuclear Medicine Division * Bedford Heights, Ohio 44128-5443 * Copyright 1990, 1991, 1992 *c *R * Revision History: * 1.1 08/04/90 J. Brack * 1.2 05/14/92 J. Brack * Cleanup for release. * 2.0 09/06/94 W. Wooten * Modify imager.c into uncmprss.c * 2.1 06/21/95 W. Wooten * change name from uncmprss.c to cmprss5.c * spawn to arch (version 2.3) with "-f" flag * 2.1a 6/26/95 W. Wooten * add a "help" button to the row col widget * 2.2 8/18/95 W. Wooten / Eugene Mah * check for gated files, if found add a wild card to * include all gated intervals * 2.2a 8/22/95 W. Wooten * fix up to process a lightbox of a gated, without * looking for all of the intervals. *r *D * Description: * Use a "Row and Column" widget to allow user to select the * Compress or Uncompress function. * Get file names from the workbench, and spawn to the arch * script. * cmprss5.c runs under BL5 software with HP widgets. There * is another version called cmprss.c that runs under BL6 * software with motif widgets. *d */ /* UNIX includes */ #include #include #include #include #include /* X Window and Xt Intrinsics includes */ #include #include #include /* only needed for TextEdit widget */ #include /* HP Widget includes */ #include #include #include #include #include #include /* Picker includes */ #include "OIXt.h" #include "OIlib.h" #include "dials.h" #include "iib.h" #include "index.h" #include "oi_cursor.h" #define NDEV 1 /* number of polled devices */ #define FDS_X 0 /* device 1 */ /* X Windows control structures */ static Display *display; /* display device */ static Window imager_window; /* X window for imager */ static XEvent report; /* X window event reports */ static XFontStruct *img_font; /* Font for imager window */ /* Xt and Xw Toolkit stuff */ #define NUM_BUT 4 /* number of buttons */ static Widget toplevel; /* top level widget */ static Widget FormW; /* Form holds all other widgets */ static Widget NameW; /* Text widget for our name */ static Widget RowColW; /* Row/Column widget for buttons */ static Widget PButtonW[NUM_BUT];/* array of pushbutton widgets */ static Widget LabelW; /* label widget */ static Widget TextEditW; /* text edit widget */ static Widget HelpShell; /* shell for help window */ static Cursor dot, hand, cross; /* mouse cursors */ /* general varible storage */ static char idnum[4]; /* our workbench ID */ static char title_buf[40]; /* our Title */ static char title[] = "File Compression Utility "; static struct iib iib; /* IIB data */ static struct pollfd fds[NDEV]; /* async device poll struct */ static int tix = 100; /* polling timeout in msec */ static int popup_x, popup_y; /* coords for popups */ static float polltix = 1./60.; /* number of polling ticks/sec */ /* list of files to be passed through the spawn to arch the 1st three arguments are used for "arch", "-C|U", and "-f" so there is room on the list for 100 files, and up to 40 characters in each path. */ char filelist[103][40]; char *list[103]; /* Function key translation for TextEdit widget */ #define KEYS 1 static struct key_s { int keysym; char *string; } map[KEYS] = { {XK_F3, "\177"} }; /* remap F3 to operate as "del" key */ /* external OIXt variables */ extern GC img_gc; /* graphic context for imager window */ /* external Unix functions */ extern char *getenv(); /* exported variable */ char *me; /******************************************************************************/ /* This function is called before a popup is created. It locates the current control panel and loads the variables "popup_x" and "popup_y" with the coordinates of the lower left corner of the panel. Popups are passed these coordinates as an origin for their application shells. We call this often because the user may "move" the panel between invocations of the popups. */ static void get_popup_coords() { Window ph_shell; XWindowAttributes shell_att; /* The "get_gramps()" function is in OIlib. Given the window of a widget, it returns the most ancestral (hence "gramps") X window containing the widget. */ ph_shell = get_gramps(display,XtWindow(toplevel)); XGetWindowAttributes(display,ph_shell,&shell_att); popup_x = shell_att.x; popup_y = shell_att.y + shell_att.height; } /******************************************************************************/ /* Clean up the user interface before exiting the program. */ static void demo_exit() { XFlush(display); /* flush all pending X operations on server */ exit( 0 ); /* and just exit */ } /******************************************************************************/ /* servicex - service X events that come in from the polling loop */ static void servicex() { Bool xt_flag; /* False when not an Xt event */ Arg arglist[1]; static char *lab; /* must be static or compiler sometimes barfs */ while(XPending(display)) { /* while some X events are waiting */ XtNextEvent(&report); /* read the event */ xt_flag = True; /* assume it is an Xt event */ switch(report.type) { /* A ButtonPress is a mouse button click. Sometimes we may want to field clicks in our imager window, so we should check which window got the click (much the same as the check above in Expose). In this case, we take the label in the TextEdit widget and place it at the click site! Notice that when we are done with the string returned by XtGetValues(), we do an XtFree() to deallocate it. This is an undocumented feature of the Intrinsics! */ case ButtonPress: if(report.xbutton.window == imager_window) { fprintf(stderr,"Mouse button #%d at (%d,%d)\n", report.xbutton.button,report.xbutton.x, report.xbutton.y); XtSetArg(arglist[0],XtNstring,&lab); XtGetValues(TextEditW,arglist,1); XDrawString(display,imager_window,img_gc, report.xbutton.x,report.xbutton.y,lab,strlen(lab)); XtFree(lab); xt_flag = False; } break; /* This is the trap door. The OIXt img_define call enables Expose, ButtonPress and ConfigureNotify events. If we get any others, there must be something amiss. If you want to enable other events, feel free. */ } /* end switch on X events */ /* Xt and/or Xw Toolkit events are handled here */ if(xt_flag) XtDispatchEvent(&report); } /* endwhile events are queued */ } /******************************************************************************/ /* This function sets a pushbutton to its "insensitive mode". */ static void go_insensitive(button) int button; { XtSetSensitive(PButtonW[button],False); /* deactivate */ XDefineCursor(display,XtWindow(PButtonW[button]),dot); /* assign dot */ } /******************************************************************************/ /* This function sets a pushbutton to its "sensitive mode". */ static void go_sensitive(button) int button; { XtSetSensitive(PButtonW[button],True); /* activate */ XDefineCursor(display,XtWindow(PButtonW[button]),hand); /* point to it */ } /******************************************************************************/ /* This function is called when the "Compress Workbench" button is hit */ static void cmp_but() { strcpy (filelist[1], "-C"); list[1]=filelist[1]; spawnv (list[0], list); exit(0); /* Exit happily. The "0" tells Workbench "success".*/ } /******************************************************************************/ /* This function is called when the "Uncompress Workbench" button is hit */ static void uncmp_but() { strcpy (filelist[1], "-U"); list[1]=filelist[1]; spawnv (list[0], list); exit(0); /* Exit happily. The "0" tells Workbench "success".*/ } /******************************************************************************/ /* This function is called when the "Help" button is hit. It calls the OIlib popup_help_shell() function, passing it the name of a text file containing information of note. Note that the file "imager.hlp" must be in the $DATA directory for the help function to work properly! */ static void help_but() { char helpfile[40]; char *datapath; extern Widget popup_help_shell(); datapath = getenv("DATA"); /* get DATA env var */ sprintf(helpfile,"%s/cmprss5.hlp",datapath); /* "/prism/data/imager.hlp" ? */ get_popup_coords(); HelpShell = popup_help_shell(popup_x,popup_y,helpfile,HELP_WORKBENCH); } /******************************************************************************/ static void dummy() { } /* dummy Xt Warning Handler */ /******************************************************************************/ main(argc,argv) int argc; char *argv[]; { extern char getopt(); extern char *optarg; Arg arglist[20]; int i; int idx; char flag; char *ifi; struct ci_s *cat; /* catalog index pointer */ struct pi_s *pat; /* patient index pointer */ struct pi_s *inputtop; /* top of index pointer */ struct btbl { char *text; char *color; caddr_t call; }; static struct btbl bt[NUM_BUT] = { { " Compress Workbench ", "tan", cmp_but }, { " Uncompress Workbench ", "orchid", uncmp_but }, { " Help ", "white", help_but }, { " Exit ", "yellow", demo_exit } }; me = argv[0]; signal(SIGINT,demo_exit); /* trap ctrl-c */ signal(SIGUSR2,SIG_IGN); /* ignore USER 2 from workbench */ /* Do the general Xwindows environment setup for the user interface. Initialize toolkit making this application a member of the "DEmo" class. See "uncmprss.def" for resource definitions! */ toplevel = XtInitialize("main","DEmo",NULL,NULL,&argc,argv); display = XtDisplay(toplevel); /* obtain the display ID */ /* Every time you use a TextEdit widget you will get the message: "X Toolkit Warning: Overriding earlier translation manager actions." Once you have debugged your application, uncomment this line to get rid of this nuisance message. */ /* XtSetWarningHandler(dummy); */ /* Parse the command line sent to us by Workbench. The definition of WORKBENCH_OPTIONS is in OIlib.h. We ignore many of these options The "getopt" function is a C library function. You can get the syntax of getopt by typing "man 3 getopt". */ while((flag = getopt(argc,argv,WORKBENCH_OPTIONS)) != -1) switch(flag) { case 'I': ifi = optarg; break; /* get index input file */ } /* Load the files "on" the Workbench into a linked list "tree" of files to be processed. */ if((inputtop = LoadInput(ifi)) == NULL) /* load tree of input files */ demo_exit(0); /* We creating the "list" to pass through the spawn to arch The first entry in the list is not a patient directory but the name of the name of new process for spawn */ strcpy (filelist[0], "/prism/site/arch"); list[0]=filelist[0]; /* The second entry in the list is the compress or uncompress flag which will be set later when a button is pushed, and the third entry in the list is the -f flag so that arch will work on files instead of directories. */ strcpy (filelist[2], "-f"); list[2]=filelist[2]; /* work through the files on the workbench set pointer to first patient index structure */ pat = inputtop; i=3; list[i]=NULL; while (( pat= NextFile(pat,&cat)) != NULL) { strcpy (filelist[i],"/"); strcat (filelist[i],cat->disk); strcat (filelist[i],"/P"); strcat (filelist[i],cat->asn); strcat (filelist[i],"/"); strcat (filelist[i],pat->filename); if(((pat->typ & IIBPRJ) >0) | ((pat->typ & IIBIMG) >0)) if((pat->at & IIBEKG) >0) strcat (filelist[i],"_*"); list[i] = filelist[i]; i++; list[i]=NULL; if (i > 100) break; } /* Make a "Form" widget to contain all other widgets and manage their geometry and layout requirements. */ FormW = XtCreateManagedWidget("Form",XwformWidgetClass,toplevel,NULL,0); /* Place a "static text" widget at the top of the form that displays our name and workbench number. */ strcpy(title_buf,title); strcat(title_buf,idnum); i = 0; XtSetArg(arglist[i],XtNxResizable,True);i++; XtSetArg(arglist[i],XtNyResizable,True);i++; XtSetArg(arglist[i],XtNxAttachRight,True);i++; XtSetArg(arglist[i],XtNvSpace,4);i++; XtSetArg(arglist[i],XtNhSpace,4);i++; XtSetArg(arglist[i],XtNstring,title_buf);i++; XtSetArg(arglist[i],XtNborderWidth,0);i++; NameW = XtCreateManagedWidget("Name",XwstatictextWidgetClass, FormW,arglist,i); /* Use a Row and Column manager under the name that will manage the pushbutton geometries and layout. */ i = 0; XtSetArg(arglist[i],XtNforceSize,True);i++; XtSetArg(arglist[i],XtNyRefWidget,NameW);i++; XtSetArg(arglist[i],XtNyAddHeight,True);i++; XtSetArg(arglist[i],XtNxOffset,4);i++; XtSetArg(arglist[i],XtNxAttachRight,True);i++; XtSetArg(arglist[i],XtNxAttachOffset,4);i++; RowColW = XtCreateManagedWidget("RowCol",XwrowColWidgetClass, FormW,arglist,i); /* Create the pushbuttons within the RowCol in a table driven loop. */ for(idx = 0; idx < NUM_BUT; idx++) { i = 0; XtSetArg(arglist[i],XtNlabel,bt[idx].text);i++; /* button text */ XtSetArg(arglist[i],XtNbackground, /* button color */ String_to_Pixel(display,NULL,bt[idx].color));i++; PButtonW[idx] = XtCreateManagedWidget("PButton", XwpushButtonWidgetClass,RowColW,arglist,i); XtAddCallback(PButtonW[idx],XtNrelease, /* button callback */ bt[idx].call,NULL); } /* Realize Widgets */ XtRealizeWidget(toplevel); /* Rebind TextEdit widget function keys */ for(i = 0; i < KEYS ; i++) XRebindKeysym(display,map[i].keysym,NULL,0,map[i].string, strlen(map[i].string)); /* assign cursors */ dot = oi_cursor(display,XC_dot,NULL,NULL); XDefineCursor(display,XtWindow(FormW),dot); /* assign dot to Form */ hand = oi_cursor(display,OI_hand,NULL,NULL); XDefineCursor(display,XtWindow(RowColW),hand); /* assign hand to buttons */ /* Setup the devices from which input to the program is expected. These devices will be polled to check for any incoming data to control the program. */ fds[FDS_X].fd = display->fd; /* the X events */ fds[FDS_X].events = POLLIN; /* Enter an infinite loop, waiting for input from any of the devices declared. In this case, we use the System V "poll" facility to wait for an X event...and if we don't see one in "tix" milliseconds, we bump some counters and look for something else to do. */ tix = 100; /* start at 100 msec ticks */ while(1) { /* start infinite loop */ if( poll(fds,NDEV,tix) != 0) { /* wait for X events */ if (fds[FDS_X].revents == POLLIN) /* if truly an X event */ servicex(); /* service the X event */ } } /* end FOREVER loop */ } /* end main */