Back to index

tetex-bin  3.0
sfSelFile.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
00003  *
00004  * Permission to use, copy, modify, and distribute this software and its
00005  * documentation for any purpose and without fee is hereby granted, provided
00006  * that the above copyright notice appear in all copies and that both that
00007  * copyright notice and this permission notice appear in supporting
00008  * documentation, and that the name of Software Research Associates not be used
00009  * in advertising or publicity pertaining to distribution of the software
00010  * without specific, written prior permission.  Software Research Associates
00011  * makes no representations about the suitability of this software for any
00012  * purpose.  It is provided "as is" without express or implied warranty.
00013  *
00014  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
00015  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
00016  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
00017  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00018  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00019  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00020  * PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  * Author: Erik M. van der Poel
00023  *         Software Research Associates, Inc., Tokyo, Japan
00024  *         erik@sra.co.jp
00025  */
00026 
00027 #include "xdvi-config.h"
00028 
00029 #include "xdvi.h"
00030 #include "dvi-init.h" /* for dviErrFlagT */
00031 #include "message-window.h"
00032 
00033 #include "kpathsea/c-stat.h"
00034 
00035 #include <string.h>
00036 
00037 #include "sfDir.h"
00038 #include "sfPath.h"
00039 #include "sfDraw.h"
00040 #include "sfSelFile.h"
00041 #include "util.h"
00042 
00043 #include <ctype.h>
00044 #include "kpathsea/c-fopen.h"
00045 #include "kpathsea/c-stat.h"
00046 
00047 #if !defined(MOTIF) /* entire file */
00048 
00049 
00050 #include <errno.h>
00051 
00052 #ifdef X_NOT_STDC_ENV
00053 extern int errno;
00054 #endif
00055 
00056 #define SEL_FILE_CANCEL            -1
00057 #define SEL_FILE_OK         0
00058 #define SEL_FILE_NULL              1
00059 #define SEL_FILE_TEXT              2
00060 
00061 /*
00062  * Author's address:
00063  *
00064  *     erik@sra.co.jp
00065  *                                            OR
00066  *     erik%sra.co.jp@uunet.uu.net
00067  *                                            OR
00068  *     erik%sra.co.jp@mcvax.uucp
00069  *                                            OR
00070  *     try junet instead of co.jp
00071  *                                            OR
00072  *     Erik M. van der Poel
00073  *     Software Research Associates, Inc.
00074  *     1-1-1 Hirakawa-cho, Chiyoda-ku
00075  *     Tokyo 102 Japan. TEL +81-3-234-2692
00076  */
00077 
00078 #include <sys/param.h>
00079 #include <X11/cursorfont.h>
00080 #include <X11/Intrinsic.h>
00081 #include <X11/StringDefs.h>
00082 #include <X11/Composite.h>
00083 #include <X11/Shell.h>
00084 #include <X11/Xaw/Paned.h>
00085 #include <X11/Xaw/Text.h>
00086 #include <X11/Xaw/AsciiText.h>
00087 #include <X11/Xaw/Form.h>
00088 #include <X11/Xaw/Command.h>
00089 #include <X11/Xaw/Scrollbar.h>
00090 #include <X11/Xaw/Label.h>
00091 #include <X11/Xaw/Cardinals.h>
00092 
00093 
00094 #ifndef MAXPATHLEN
00095 #define MAXPATHLEN 1024
00096 #endif /* ndef MAXPATHLEN */
00097 
00098 /* global vars for communication with sfDraw.c */
00099 char SFstartDir[MAXPATHLEN], SFcurrentPath[MAXPATHLEN], SFcurrentDir[MAXPATHLEN];
00100 Widget selFileField, selFileForm, selFileHScroll, selFileHScrolls[3], selFileLists[3], selFileVScrolls[3];
00101 Display *SFdisplay;
00102 Pixel SFfore, SFback;
00103 XSegment SFsegs[2], SFcompletionSegs[2];
00104 XawTextPosition SFtextPos;
00105 int SFupperX, SFlowerY, SFupperY;
00106 int SFtextX, SFtextYoffset;
00107 int SFentryWidth, SFentryHeight;
00108 int SFlineToTextH = 3;
00109 int SFlineToTextV = 3;
00110 int SFbesideText = 3;
00111 int SFaboveAndBelowText = 2;
00112 int SFcharsPerEntry = 15;
00113 int SFlistSize = 10;
00114 int SFworkProcAdded = 0;
00115 XtAppContext SFapp;
00116 int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
00117 char SFtextBuffer[MAXPATHLEN];
00118 XtIntervalId SFdirModTimerId;
00119 int (*SFfunc) ();
00120 
00121 static int SFstatus = SEL_FILE_NULL;
00122 
00123 static Widget selFile, selFileCancel, selFileOK, selFilePrompt;
00124 /* For file filter. */
00125 static Widget selFileLabel, selFileMask, selFileHide;
00126 
00127 #define MASKWIDTH 16
00128 static char fileMask[MASKWIDTH + 2] = "*.dvi";
00129 
00130 static Atom SFwmDeleteWindow;
00131 
00132 static char *oneLineTextEditTranslations =
00133     "<Key>Return: redraw-display()\n"
00134     "Ctrl<Key>M: redraw-display()\n";
00135 
00136 #if !defined (HAVE_STRERROR) && !defined (strerror)
00137 static char *
00138 strerror(int errnum)
00139 {
00140     return 0 < errnum && errnum <= sys_nerr
00141        ? sys_errlist[errnum] : "Unknown system error";
00142 }
00143 #endif /* not HAVE_STRERROR && not strerror */
00144 
00145 void
00146 raise_file_selector(void)
00147 {
00148     if (selFile != 0) {
00149        XRaiseWindow(DISP, XtWindow(selFile));
00150     }
00151 }
00152 
00153 static void
00154 SFexposeList(Widget w, XtPointer n, XEvent *event, Boolean *cont)
00155 {
00156     UNUSED(w);
00157     UNUSED(cont);
00158     
00159     if ((event->type == NoExpose) || event->xexpose.count) {
00160        return;
00161     }
00162 
00163     SFdrawList((int)n, SF_DO_NOT_SCROLL);
00164 }
00165 
00166 static void
00167 SFmodVerifyCallback(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
00168 {
00169     char buf[2];
00170 
00171     UNUSED(w);
00172     UNUSED(client_data);
00173     UNUSED(cont);
00174     
00175     if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
00176        ((*buf) == '\r')) {
00177        SFstatus = SEL_FILE_OK;
00178     }
00179     else {
00180        SFstatus = SEL_FILE_TEXT;
00181     }
00182 }
00183 
00184 static void
00185 SFokCallback(Widget w, XtPointer cl, XtPointer cd)
00186 {
00187     UNUSED(w);
00188     UNUSED(cl);
00189     UNUSED(cd);
00190     
00191     SFstatus = SEL_FILE_OK;
00192 }
00193 
00194 static XtCallbackRec SFokSelect[] = {
00195     {SFokCallback, (XtPointer) NULL},
00196     {NULL, (XtPointer) NULL},
00197 };
00198 
00199 static void
00200 SFcancelCallback(Widget w, XtPointer cl, XtPointer cd)
00201 {
00202     UNUSED(w);
00203     UNUSED(cl);
00204     UNUSED(cd);
00205     
00206     SFstatus = SEL_FILE_CANCEL;
00207 }
00208 
00209 static XtCallbackRec SFcancelSelect[] = {
00210     {SFcancelCallback, (XtPointer) NULL},
00211     {NULL, (XtPointer) NULL},
00212 };
00213 
00214 static void
00215 SFdismissAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
00216 {
00217     UNUSED(w);
00218     UNUSED(params);
00219     UNUSED(num_params);
00220     
00221     if (event->type == ClientMessage && (unsigned)(event->xclient.data.l[0]) != SFwmDeleteWindow)
00222        return;
00223 
00224     SFstatus = SEL_FILE_CANCEL;
00225 }
00226 
00227 static char *wmDeleteWindowTranslation = "<Message>WM_PROTOCOLS: SelFileDismiss()\n";
00228 
00229 static XtActionsRec sf_actions[] = {
00230     {"SelFileDismiss", SFdismissAction},
00231 };
00232 
00233 /* Don't show files that don't get through the filter.  */
00234 
00235 /* return 1 if file is masked (mask does not match filename), 0 otherwise */
00236 static int
00237 maskFile(const char *mask, char *filename)
00238 {
00239     int c, c1;
00240 
00241     while ((c = *mask++)) {
00242        if (c == '*') {
00243            while ((c1 = *mask++)) {
00244               if (c1 != '*') {
00245                   if (!(*filename))
00246                      return 1;
00247                   if (c1 != '?') {
00248                      while ((filename = strchr(filename, c1))) {
00249                          if (!maskFile(mask, ++filename))
00250                             return 0;
00251                      }
00252                      return 1;
00253                   }
00254                   else
00255                      filename++;
00256               }
00257            }
00258            return 0;
00259        }
00260        if (c == '?') {
00261            if (!*filename)
00262               return 1;
00263        }
00264        else if (c != *filename)
00265            return 1;
00266        filename++;
00267     }
00268     return (*filename) ? 1 : 0;
00269 }
00270 
00271 Boolean hideFlag = False;
00272 static int
00273 showEntry(char *entryReal, char **entryShown, struct stat *statBuf)
00274 {
00275     UNUSED(entryShown);
00276 
00277     if ((hideFlag && entryReal[0] == '.') || (!S_ISDIR(statBuf->st_mode) && maskFile(fileMask, entryReal)))
00278        return 0;
00279     entryReal[strlen(entryReal)] = SFstatChar(statBuf);
00280     return 1;
00281 }
00282 
00283 static void
00284 maskChanged(Widget w, XtPointer client_data, XEvent *call_data, Boolean *cont)
00285 {
00286     char buf[2];
00287     SFDir *dir;
00288 
00289     UNUSED(w);
00290     UNUSED(client_data);
00291     UNUSED(cont);
00292     
00293     if ((XLookupString((XKeyPressedEvent *)call_data, buf, 2, NULL, NULL) == 1) && ((*buf) == '\r')) {
00294        for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
00295            *(dir->dir) = 0; /* force a re-read */
00296        SFupdatePath();
00297     }
00298 }
00299 
00300 static void
00301 hideFiles(Widget w, XtPointer client_data, XtPointer call_data)
00302 {
00303     SFDir *dir;
00304     SFEntry *entry;
00305 
00306     UNUSED(client_data);
00307     UNUSED(call_data);
00308     
00309     hideFlag = !hideFlag;
00310     if (hideFlag) {
00311        XtVaSetValues(w, XtNlabel, "hidden", NULL);
00312        for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
00313            if (!(dir->nEntries))
00314               continue;
00315            dir->vOrigin = 0;
00316            for (entry = &(dir->entries[dir->nEntries - 1]);
00317                entry >= dir->entries; entry--)
00318               entry->statDone = 0;
00319            SFdrawLists(SF_DO_SCROLL);
00320        }
00321     }
00322     else {
00323        XtVaSetValues(w, XtNlabel, "shown", NULL);
00324        for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
00325            *(dir->dir) = 0; /* force a re-read */
00326        SFupdatePath();
00327     }
00328 }
00329 
00330 
00331 static Widget
00332 SFcreateWidgets(Widget parent, const char *title, const char *prompt, const char *ok, const char *cancel)
00333 {
00334     Cardinal i, n;
00335     int listWidth, listHeight;
00336     int listSpacing = 10;
00337     int scrollThickness = 15;
00338     int hScrollX, hScrollY;
00339     int vScrollX, vScrollY;
00340     Cursor xtermCursor, sbRightArrowCursor, arrowCursor;
00341     Arg arglist[20];
00342     Widget paned, box;
00343     
00344     i = 0;
00345     XtSetArg(arglist[i], XtNtransientFor, parent);
00346     XtSetArg(arglist[i], XtNtitle, title);
00347     i++;
00348 
00349     selFile = XtAppCreateShell("xdviSelFile", "XdviSelFile",
00350                             transientShellWidgetClass, SFdisplay,
00351                             arglist, i);
00352 
00353     /* Add WM_DELETE_WINDOW protocol */
00354     XtAppAddActions(XtWidgetToApplicationContext(selFile),
00355                   sf_actions, XtNumber(sf_actions));
00356     XtOverrideTranslations(selFile,
00357                         XtParseTranslationTable(wmDeleteWindowTranslation));
00358 
00359     paned = XtVaCreateManagedWidget("paned", panedWidgetClass, selFile, NULL);
00360     i = 0;
00361     XtSetArg(arglist[i], XtNdefaultDistance, 6);
00362     i++;
00363     selFileForm = XtCreateManagedWidget("selFileForm",
00364                                    formWidgetClass, paned, arglist, i);
00365 
00366     i = 0;
00367     XtSetArg(arglist[i], XtNlabel, prompt);
00368     i++;
00369     XtSetArg(arglist[i], XtNresizable, True);
00370     i++;
00371     XtSetArg(arglist[i], XtNtop, XtChainTop);
00372     i++;
00373     XtSetArg(arglist[i], XtNbottom, XtChainTop);
00374     i++;
00375     XtSetArg(arglist[i], XtNleft, XtChainLeft);
00376     i++;
00377     XtSetArg(arglist[i], XtNright, XtChainLeft);
00378     i++;
00379     XtSetArg(arglist[i], XtNborderWidth, 0);
00380     i++;
00381     XtSetArg(arglist[i], XtNvertDistance, 20);
00382     i++;
00383     selFilePrompt = XtCreateManagedWidget("selFilePrompt",
00384                                      labelWidgetClass, selFileForm,
00385                                      arglist, i);
00386 
00387 #if 1
00388     i = 0;
00389     XtSetArg(arglist[i], XtNforeground, &SFfore);
00390     i++;
00391     XtSetArg(arglist[i], XtNbackground, &SFback);
00392     i++;
00393     XtGetValues(selFilePrompt, arglist, i);
00394 #endif
00395 
00396     SFinitFont();
00397 
00398     SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth + SFbesideText;
00399     SFentryHeight = SFaboveAndBelowText + SFcharHeight + SFaboveAndBelowText;
00400 
00401     listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
00402        scrollThickness;
00403     listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
00404        SFlineToTextV + SFlistSize * SFentryHeight +
00405        SFlineToTextV + 1 + scrollThickness;
00406 
00407     SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
00408 
00409     hScrollX = -1;
00410     hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
00411        SFlineToTextV + SFlistSize * SFentryHeight + SFlineToTextV;
00412     SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
00413 
00414     vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
00415     vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
00416     SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
00417        SFlineToTextV;
00418 
00419     SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
00420     SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
00421        SFlineToTextV;
00422     SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
00423        SFlineToTextV + SFlistSize * SFentryHeight - 1;
00424 
00425     SFtextX = SFlineToTextH + SFbesideText;
00426     SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
00427 
00428     SFsegs[0].x1 = 0;
00429     SFsegs[0].y1 = vScrollY;
00430     SFsegs[0].x2 = vScrollX - 1;
00431     SFsegs[0].y2 = vScrollY;
00432     SFsegs[1].x1 = vScrollX;
00433     SFsegs[1].y1 = 0;
00434     SFsegs[1].x2 = vScrollX;
00435     SFsegs[1].y2 = vScrollY - 1;
00436 
00437     SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
00438     SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
00439        SFlineToTextH + SFentryWidth - 1;
00440 
00441     i = 0;
00442 /*     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4 - w - 10); */
00443     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
00444     i++;
00445 /*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
00446 /*      i++; */
00447 
00448 /*     XtSetArg(arglist[i], XtNfromHoriz, selFilePrompt); */
00449 /*     i++; */
00450 /*     XtSetArg(arglist[i], XtNhorizDistance, 10); */
00451     XtSetArg(arglist[i], XtNfromVert, selFilePrompt);
00452     i++;
00453 /*      XtSetArg(arglist[i], XtNvertDistance, 0); */
00454 /*      i++; */
00455     XtSetArg(arglist[i], XtNresizable, True);
00456     i++;
00457     XtSetArg(arglist[i], XtNtop, XtChainTop);
00458     i++;
00459     XtSetArg(arglist[i], XtNbottom, XtChainTop);
00460     i++;
00461     XtSetArg(arglist[i], XtNleft, XtChainLeft);
00462     i++;
00463     XtSetArg(arglist[i], XtNright, XtChainLeft);
00464     i++;
00465     XtSetArg(arglist[i], XtNstring, SFtextBuffer);
00466     i++;
00467     XtSetArg(arglist[i], XtNlength, MAXPATHLEN);
00468     i++;
00469     XtSetArg(arglist[i], XtNeditType, XawtextEdit);
00470     i++;
00471     XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);
00472     i++;
00473     XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);
00474     i++;
00475     XtSetArg(arglist[i], XtNuseStringInPlace, True);
00476     i++;
00477     XtSetArg(arglist[i], XtNvertDistance, 5);
00478     i++;
00479     selFileField = XtCreateManagedWidget("selFileField",
00480                                       asciiTextWidgetClass, selFileForm,
00481                                       arglist, i);
00482 
00483     XtOverrideTranslations(selFileField,
00484                         XtParseTranslationTable
00485                         (oneLineTextEditTranslations));
00486 /*     XtSetKeyboardFocus(selFileForm, selFileField);
00487        need focus for selFileMask widget to set the filter */
00488 
00489     i = 0;
00490     XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
00491     i++;
00492     XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);
00493     i++;
00494     XtSetArg(arglist[i], XtNheight, scrollThickness);
00495     i++;
00496 /*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
00497 /*      i++; */
00498     XtSetArg(arglist[i], XtNfromVert, selFileField);
00499     i++;
00500     XtSetArg(arglist[i], XtNvertDistance, 30);
00501     i++;
00502     XtSetArg(arglist[i], XtNtop, XtChainTop);
00503     i++;
00504     XtSetArg(arglist[i], XtNbottom, XtChainTop);
00505     i++;
00506     XtSetArg(arglist[i], XtNleft, XtChainLeft);
00507     i++;
00508     XtSetArg(arglist[i], XtNright, XtChainLeft);
00509     i++;
00510     selFileHScroll = XtCreateManagedWidget("selFileHScroll",
00511                                       scrollbarWidgetClass, selFileForm,
00512                                       arglist, i);
00513 
00514     XtAddCallback(selFileHScroll, XtNjumpProc,
00515                 (XtCallbackProc)SFpathSliderMovedCallback, (XtPointer) NULL);
00516     XtAddCallback(selFileHScroll, XtNscrollProc,
00517                 (XtCallbackProc)SFpathAreaSelectedCallback, (XtPointer) NULL);
00518 
00519     i = 0;
00520     XtSetArg(arglist[i], XtNwidth, listWidth);
00521     i++;
00522     XtSetArg(arglist[i], XtNheight, listHeight);
00523     i++;
00524 /*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
00525 /*      i++; */
00526     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
00527     i++;
00528     XtSetArg(arglist[i], XtNvertDistance, 10);
00529     i++;
00530     XtSetArg(arglist[i], XtNtop, XtChainTop);
00531     i++;
00532     XtSetArg(arglist[i], XtNbottom, XtChainTop);
00533     i++;
00534     XtSetArg(arglist[i], XtNleft, XtChainLeft);
00535     i++;
00536     XtSetArg(arglist[i], XtNright, XtChainLeft);
00537     i++;
00538     selFileLists[0] = XtCreateManagedWidget("selFileList1",
00539                                        compositeWidgetClass, selFileForm,
00540                                        arglist, i);
00541 
00542     i = 0;
00543     XtSetArg(arglist[i], XtNwidth, listWidth);
00544     i++;
00545     XtSetArg(arglist[i], XtNheight, listHeight);
00546     i++;
00547 /*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
00548 /*      i++; */
00549     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);
00550     i++;
00551     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
00552     i++;
00553     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);
00554     i++;
00555     XtSetArg(arglist[i], XtNvertDistance, 10);
00556     i++;
00557     XtSetArg(arglist[i], XtNtop, XtChainTop);
00558     i++;
00559     XtSetArg(arglist[i], XtNbottom, XtChainTop);
00560     i++;
00561     XtSetArg(arglist[i], XtNleft, XtChainLeft);
00562     i++;
00563     XtSetArg(arglist[i], XtNright, XtChainLeft);
00564     i++;
00565     selFileLists[1] = XtCreateManagedWidget("selFileList2",
00566                                        compositeWidgetClass, selFileForm,
00567                                        arglist, i);
00568 
00569     i = 0;
00570     XtSetArg(arglist[i], XtNwidth, listWidth);
00571     i++;
00572     XtSetArg(arglist[i], XtNheight, listHeight);
00573     i++;
00574 /*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
00575 /*      i++; */
00576     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);
00577     i++;
00578     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
00579     i++;
00580     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);
00581     i++;
00582     XtSetArg(arglist[i], XtNvertDistance, 10);
00583     i++;
00584     XtSetArg(arglist[i], XtNtop, XtChainTop);
00585     i++;
00586     XtSetArg(arglist[i], XtNbottom, XtChainTop);
00587     i++;
00588     XtSetArg(arglist[i], XtNleft, XtChainLeft);
00589     i++;
00590     XtSetArg(arglist[i], XtNright, XtChainLeft);
00591     i++;
00592     selFileLists[2] = XtCreateManagedWidget("selFileList3",
00593                                        compositeWidgetClass, selFileForm,
00594                                        arglist, i);
00595 
00596     for (n = 0; n < 3; n++) {
00597 
00598        i = 0;
00599        XtSetArg(arglist[i], XtNx, vScrollX);
00600        i++;
00601        XtSetArg(arglist[i], XtNy, vScrollY);
00602        i++;
00603        XtSetArg(arglist[i], XtNwidth, scrollThickness);
00604        i++;
00605        XtSetArg(arglist[i], XtNheight, SFvScrollHeight);
00606        i++;
00607 /*     XtSetArg(arglist[i], XtNborderColor, SFfore); */
00608 /*     i++; */
00609        selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
00610                                              scrollbarWidgetClass,
00611                                              selFileLists[n], arglist, i);
00612 
00613        XtAddCallback(selFileVScrolls[n], XtNjumpProc,
00614                     (XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer) n);
00615        XtAddCallback(selFileVScrolls[n], XtNscrollProc,
00616                     (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer) n);
00617 
00618        i = 0;
00619 
00620        XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
00621        i++;
00622        XtSetArg(arglist[i], XtNx, hScrollX);
00623        i++;
00624        XtSetArg(arglist[i], XtNy, hScrollY);
00625        i++;
00626        XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);
00627        i++;
00628        XtSetArg(arglist[i], XtNheight, scrollThickness);
00629        i++;
00630 /*     XtSetArg(arglist[i], XtNborderColor, SFfore); */
00631 /*     i++; */
00632        selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
00633                                              scrollbarWidgetClass,
00634                                              selFileLists[n], arglist, i);
00635 
00636        XtAddCallback(selFileHScrolls[n], XtNjumpProc,
00637                     (XtCallbackProc)SFhSliderMovedCallback, (XtPointer) n);
00638        XtAddCallback(selFileHScrolls[n], XtNscrollProc,
00639                     (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer) n);
00640     }
00641 
00642     /* Do the file filter stuff.  */
00643     selFileLabel = XtVaCreateManagedWidget("selFileLabel",
00644                                       labelWidgetClass, selFileForm,
00645                                       XtNfromVert, selFileLists[0],
00646                                       XtNvertDistance, 30,
00647 /*                                    XtNfromHoriz, selFileCancel, */
00648 /*                                    XtNhorizDistance, 60, */
00649                                       XtNlabel, "File Mask:",
00650                                       XtNborderWidth, 0,
00651                                       XtNtop, XtChainTop,
00652                                       XtNbottom, XtChainTop, NULL);
00653 
00654     selFileMask = XtVaCreateManagedWidget("selFileMask",
00655                                      asciiTextWidgetClass, selFileForm,
00656                                      XtNwidth, MASKWIDTH / 2 * SFcharWidth,
00657                                      XtNfromVert, selFileLists[0],
00658                                      XtNvertDistance, 30,
00659                                      XtNfromHoriz, selFileLabel,
00660                                      XtNhorizDistance, 0,
00661                                      XtNtop, XtChainTop,
00662                                      XtNbottom, XtChainTop,
00663                                      XtNstring, fileMask,
00664                                      XtNlength, MASKWIDTH,
00665                                      XtNeditType, XawtextEdit,
00666                                      XtNwrap, XawtextWrapNever,
00667                                      XtNuseStringInPlace, True, NULL);
00668 
00669     for (i = 0; i < 3; i++)
00670        XtSetKeyboardFocus(selFileLists[i], selFileField);
00671 
00672     XtOverrideTranslations(selFileMask,
00673                         XtParseTranslationTable
00674                         (oneLineTextEditTranslations));
00675 
00676     XtAddEventHandler(selFileMask, KeyPressMask, False,
00677                     (XtEventHandler)maskChanged, (XtPointer) NULL);
00678 
00679     selFileLabel = XtVaCreateManagedWidget("selFileLabel",
00680                                       labelWidgetClass, selFileForm,
00681                                       XtNfromVert, selFileLists[0],
00682                                       XtNvertDistance, 30,
00683                                       XtNfromHoriz, selFileMask,
00684                                       XtNhorizDistance, 40,
00685                                       XtNlabel, "Dot files are:",
00686                                       XtNborderWidth, 0,
00687                                       XtNtop, XtChainTop,
00688                                       XtNbottom, XtChainTop, NULL);
00689 
00690     selFileHide = XtVaCreateManagedWidget("selFileHide",
00691                                      commandWidgetClass, selFileForm,
00692 /*                                   XtNwidth, 7 * SFcharWidth, */
00693                                      XtNfromVert, selFileLists[0],
00694                                      XtNvertDistance, 30,
00695                                      XtNfromHoriz, selFileLabel,
00696                                      XtNhorizDistance, 2,
00697                                      XtNlabel, hideFlag ? "hidden" : "shown",
00698 /*                                   XtNborderWidth, 1, */
00699                                      XtNtop, XtChainTop,
00700 /*                                   XtNjustify, XtJustifyLeft, */
00701                                      XtNbottom, XtChainTop,
00702                                      NULL);
00703     XtAddCallback(selFileHide, XtNcallback, (XtCallbackProc)hideFiles, NULL);
00704 
00705     box = XtVaCreateManagedWidget("box", formWidgetClass,
00706                               paned,
00707                               XtNshowGrip, False,
00708                               XtNdefaultDistance, 6,
00709                               XtNskipAdjust, True,
00710                               XtNaccelerators, G_accels_cr,
00711                               NULL);
00712     selFileOK = XtVaCreateManagedWidget("selFileOK", commandWidgetClass,
00713                                   box,
00714                                   XtNlabel, ok,
00715                                   XtNcallback, SFokSelect,
00716                                   XtNtop, XtChainTop,
00717                                   XtNbottom, XtChainBottom,
00718                                   XtNleft, XtChainLeft,
00719                                   XtNright, XtChainLeft,
00720                                   NULL);
00721     selFileCancel = XtVaCreateManagedWidget("selFileCancel", commandWidgetClass,
00722                                        box,
00723                                        XtNlabel, cancel,
00724                                        XtNcallback, SFcancelSelect,
00725 /*                                     XtNborderColor, SFfore, */
00726                                        XtNfromHoriz, selFileOK,
00727                                        XtNbottom, XtChainBottom,
00728                                        XtNleft, XtChainRight,
00729                                        XtNright, XtChainRight,
00730                                        NULL);
00731 
00732     XtSetMappedWhenManaged(selFile, False);
00733     XtRealizeWidget(selFile);
00734 
00735     /* Add WM_DELETE_WINDOW protocol */
00736     SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
00737     XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
00738 
00739     SFcreateGC();
00740 
00741     xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
00742 
00743     sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
00744     arrowCursor = XCreateFontCursor(SFdisplay, XC_left_ptr);
00745 
00746     XDefineCursor(SFdisplay, XtWindow(selFileForm), arrowCursor);
00747     XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
00748 
00749     for (n = 0; n < 3; n++) {
00750        XDefineCursor(SFdisplay, XtWindow(selFileLists[n]), sbRightArrowCursor);
00751     }
00752     XDefineCursor(SFdisplay, XtWindow(selFileOK), arrowCursor);
00753     XDefineCursor(SFdisplay, XtWindow(selFileCancel), arrowCursor);
00754 
00755     for (n = 0; n < 3; n++) {
00756        XtAddEventHandler(selFileLists[n], ExposureMask, True,
00757                        (XtEventHandler)SFexposeList, (XtPointer) n);
00758        XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
00759                        (XtEventHandler)SFenterList, (XtPointer) n);
00760        XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
00761                        (XtEventHandler)SFleaveList, (XtPointer) n);
00762        XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
00763                        (XtEventHandler)SFmotionList, (XtPointer) n);
00764        XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
00765                        (XtEventHandler)SFbuttonPressList, (XtPointer) n);
00766        XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
00767                        (XtEventHandler)SFbuttonReleaseList, (XtPointer) n);
00768     }
00769 
00770     XtAddEventHandler(selFileField, KeyPressMask, False,
00771                     (XtEventHandler)SFmodVerifyCallback, (XtPointer) NULL);
00772 
00773     SFapp = XtWidgetToApplicationContext(selFile);
00774     return selFile;
00775 }
00776 
00777 /* position widget under the cursor */
00778 void
00779 SFpositionWidget(Widget w)
00780 {
00781     Arg args[3];
00782     Cardinal num_args;
00783     Dimension width, height, b_width;
00784     int x, y, max_x, max_y;
00785     Window root, child;
00786     int dummyx, dummyy;
00787     unsigned int dummymask;
00788 
00789     XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
00790                 &dummyx, &dummyy, &dummymask);
00791     num_args = 0;
00792     XtSetArg(args[num_args], XtNwidth, &width);
00793     num_args++;
00794     XtSetArg(args[num_args], XtNheight, &height);
00795     num_args++;
00796     XtSetArg(args[num_args], XtNborderWidth, &b_width);
00797     num_args++;
00798     XtGetValues(w, args, num_args);
00799 
00800     width += 2 * b_width;
00801     height += 2 * b_width;
00802 
00803     x -= ((Position) width / 2);
00804     if (x < 0)
00805        x = 0;
00806     if (x > (max_x = (Position) (XtScreen(w)->width - width)))
00807        x = max_x;
00808 
00809     y -= ((Position) height / 2);
00810     if (y < 0)
00811        y = 0;
00812     if (y > (max_y = (Position) (XtScreen(w)->height - height)))
00813        y = max_y;
00814 
00815     num_args = 0;
00816     XtSetArg(args[num_args], XtNx, x);
00817     num_args++;
00818     XtSetArg(args[num_args], XtNy, y);
00819     num_args++;
00820     XtSetValues(w, args, num_args);
00821 }
00822 
00823 
00824 FILE *
00825 SFopenFile(const char *name, const char *mode, const char *prompt, const char *failed)
00826 {
00827     Arg args[1];
00828     FILE *fp;
00829 
00830     UNUSED(args);
00831     UNUSED(prompt);
00832     UNUSED(failed);
00833     
00834     SFchdir(SFstartDir);
00835     errno = 0;
00836     if (!name || *name == 0 || (fp = XFOPEN(name, mode)) == NULL) {
00837        XBell(DISP, 0);
00838        return NULL;
00839     }
00840     return fp;
00841 }
00842 
00843 void
00844 SFtextChanged(void)
00845 {
00846     if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
00847        (void)strcpy(SFcurrentPath, SFtextBuffer);
00848 
00849        SFtextPos = XawTextGetInsertionPoint(selFileField);
00850     }
00851     else {
00852        (void)strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
00853 
00854        SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
00855     }
00856 
00857     if (!SFworkProcAdded) {
00858        (void)XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
00859        SFworkProcAdded = 1;
00860     }
00861 
00862     SFupdatePath();
00863 }
00864 
00865 static void
00866 SFprepareToReturn(void)
00867 {
00868     SFstatus = SEL_FILE_NULL;
00869     /* XtRemoveGrab(selFile); */
00870     XtUnmapWidget(selFile);
00871 
00872     if (SFdirModTimerId) {
00873        XtRemoveTimeOut(SFdirModTimerId);
00874        SFdirModTimerId = 0;
00875     }
00876     if (SFchdir(SFstartDir)) {
00877        XtAppError(SFapp, "XsraSelFile: can't return to current directory");
00878     }
00879 }
00880 
00881 void
00882 XsraSelFile(Widget parent, struct filesel_callback *callback)
00883 /*         const char *title, const char *prompt, */
00884 /*         const char *ok, const char *cancel, */
00885 /*         const char *init_path, */
00886 /*         const char *mask, */
00887 /*         Boolean must_exist, */
00888 /*         Widget *ret_widget */
00889 {
00890     static Boolean firstTime = True;
00891     Widget w;
00892     Cardinal i;
00893     Arg arglist[20];
00894     XEvent event;
00895     
00896     if (!callback->prompt) {
00897        callback->prompt = "Pathname:";
00898     }
00899 
00900     if (!callback->title) {
00901        callback->title = "Xdvi: select filename";
00902     }
00903 
00904     if (!callback->ok) {
00905        callback->ok = "OK";
00906     }
00907 
00908     if (!callback->cancel) {
00909        callback->cancel = "Cancel";
00910     }
00911 
00912     if (firstTime) {
00913        firstTime = False;
00914        SFdisplay = XtDisplay(parent);
00915        w = SFcreateWidgets(parent, callback->title, callback->prompt, callback->ok, callback->cancel);
00916     }
00917     else {
00918        i = 0;
00919        XtSetArg(arglist[i], XtNlabel, callback->prompt);
00920        i++;
00921        XtSetValues(selFilePrompt, arglist, i);
00922 
00923        i = 0;
00924        XtSetArg(arglist[i], XtNlabel, callback->ok);
00925        i++;
00926        XtSetValues(selFileOK, arglist, i);
00927 
00928        i = 0;
00929        XtSetArg(arglist[i], XtNlabel, callback->cancel);
00930        i++;
00931        XtSetValues(selFileCancel, arglist, i);
00932     }
00933 
00934     SFpositionWidget(selFile);
00935     XtMapWidget(selFile);
00936 
00937     {
00938        char *cwd = xgetcwd();
00939        strcpy(SFstartDir, cwd);
00940        free(cwd);
00941     }
00942     if (SFstartDir[0] == 0) {
00943        XtAppError(SFapp, "XsraSelFile: can't get current directory");
00944     }
00945     (void)strcat(SFstartDir, "/");
00946     (void)strcpy(SFcurrentDir, SFstartDir);
00947 
00948     if (callback->init_path) {
00949        if (callback->init_path[0] == '/') {
00950            (void)strcpy(SFcurrentPath, callback->init_path);
00951            if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
00952               SFsetText(SFcurrentPath);
00953            }
00954            else {
00955               SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
00956            }
00957        }
00958        else {
00959            (void)strcat(strcpy(SFcurrentPath, SFstartDir), callback->init_path);
00960            SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
00961        }
00962     }
00963     else {
00964        SFsetText(SFcurrentDir);
00965        (void)strcpy(SFcurrentPath, SFstartDir);
00966     }
00967 
00968     SFfunc = showEntry;
00969 
00970     SFtextChanged();
00971 
00972     /* don't grab the pointer so that warning popups still work */
00973     /* XtAddGrab(selFile, True, True); */
00974 
00975     SFdirModTimerId = XtAppAddTimeOut(SFapp, 1200UL,
00976                                   SFdirModTimer, (XtPointer) NULL);
00977     
00978     if (strcmp(fileMask, callback->filemask) != 0) { /* if mask changed */
00979        SFDir *dir;
00980        strncpy(fileMask, callback->filemask, MASKWIDTH);
00981        XtVaSetValues(selFileMask, XtNstring, fileMask, NULL);
00982        for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
00983            *(dir->dir) = 0; /* force a re-read */
00984        SFupdatePath();
00985     }
00986 
00987     while (1) {
00988        XtAppNextEvent(SFapp, &event);
00989        switch (event.type) {
00990            Widget w;
00991 #if 0 /* don't do this, it may send the X server into a busy loop if the File selector
00992         is positioned over a window that is `on top' by default */
00993        case Expose:
00994            if (!raise_message_windows())
00995               raise_file_selector();
00996            break;
00997 #endif
00998        case KeyPress:
00999        case ButtonPress:
01000            /* beep if keypress was inside main window */
01001            w = XtWindowToWidget(DISP, event.xany.window);
01002            while ((w != NULL) && (w != selFile)) {
01003               /* exception: message windows */
01004               if (is_message_window(w))
01005                   break;
01006               w = XtParent(w);
01007            }
01008            if (w == NULL || w == globals.widgets.top_level) {
01009               XBell(DISP, 0);
01010            }
01011            break;
01012        }
01013 
01014        XtDispatchEvent(&event);
01015 
01016        switch (SFstatus) {
01017        case SEL_FILE_TEXT:
01018            SFstatus = SEL_FILE_NULL;
01019            SFtextChanged();
01020            break;
01021        case SEL_FILE_OK:
01022            if (callback->must_exist) {
01023               FILE *tmp_fp = XFOPEN(SFtextBuffer, "r");
01024               dviErrFlagT errflag = NO_ERROR;
01025               if (tmp_fp == NULL) {
01026                   popup_message(selFile,
01027                               MSG_ERR, NULL, "Could not open %s: %s.\n",
01028                               SFtextBuffer, strerror(errno));
01029                   SFstatus = SEL_FILE_NULL;
01030                   break;
01031               }
01032               else if (!process_preamble(tmp_fp, &errflag)
01033                       || !find_postamble(tmp_fp, &errflag)
01034                       || !read_postamble(tmp_fp, &errflag, False)) {
01035                   popup_message(selFile,
01036                               MSG_ERR, NULL, "Error opening %s:\n%s.",
01037                               SFtextBuffer, get_dvi_error(errflag));
01038                   fclose(tmp_fp);
01039                   SFstatus = SEL_FILE_NULL;
01040                   break;
01041               }
01042               else { /* file is OK */
01043                   fclose(tmp_fp);
01044                   SFprepareToReturn();
01045                   callback->func_ptr(SFtextBuffer, callback->data);
01046                   return;
01047 /*                return xstrdup(SFtextBuffer); */
01048               }
01049            }
01050            else {
01051               SFprepareToReturn();
01052               callback->func_ptr(SFtextBuffer, callback->data);
01053               return;
01054 /*            return xstrdup(SFtextBuffer); */
01055            }
01056        case SEL_FILE_CANCEL:
01057            SFprepareToReturn();
01058            if (callback->exit_on_cancel)
01059               exit(0);
01060            return;
01061 /*         return NULL; */
01062        case SEL_FILE_NULL:
01063            break;
01064        }
01065     }
01066 }
01067 
01068 #else
01069 /* silence `empty compilation unit' warnings */
01070 static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
01071 #endif /* !defined(MOTIF) */