Logo Search packages:      
Sourcecode: xdvik-ja version File versions  Download package

sfSelFile.c

/*
 * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Software Research Associates not be used
 * in advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  Software Research Associates
 * makes no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
 * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author: Erik M. van der Poel
 *         Software Research Associates, Inc., Tokyo, Japan
 *         erik@sra.co.jp
 */

#include "xdvi-config.h"

#include "xdvi.h"
#include "dvi-init.h" /* for dviErrFlagT */
#include "message-window.h"

#include "kpathsea/c-stat.h"

#include <string.h>

#include "sfDir.h"
#include "sfPath.h"
#include "sfDraw.h"
#include "sfSelFile.h"
#include "util.h"

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

#if !defined(MOTIF) /* entire file */


#include <errno.h>

#ifdef      X_NOT_STDC_ENV
extern int errno;
#endif

#define SEL_FILE_CANCEL       -1
#define SEL_FILE_OK           0
#define SEL_FILE_NULL         1
#define SEL_FILE_TEXT         2

/*
 * Author's address:
 *
 *     erik@sra.co.jp
 *                                            OR
 *     erik%sra.co.jp@uunet.uu.net
 *                                            OR
 *     erik%sra.co.jp@mcvax.uucp
 *                                            OR
 *     try junet instead of co.jp
 *                                            OR
 *     Erik M. van der Poel
 *     Software Research Associates, Inc.
 *     1-1-1 Hirakawa-cho, Chiyoda-ku
 *     Tokyo 102 Japan. TEL +81-3-234-2692
 */

#include <sys/param.h>
#include <X11/cursorfont.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Composite.h>
#include <X11/Shell.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Cardinals.h>


#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif /* ndef MAXPATHLEN */

/* global vars for communication with sfDraw.c */
char SFstartDir[MAXPATHLEN], SFcurrentPath[MAXPATHLEN], SFcurrentDir[MAXPATHLEN];
Widget selFileField, selFileForm, selFileHScroll, selFileHScrolls[3], selFileLists[3], selFileVScrolls[3];
Display *SFdisplay;
Pixel SFfore, SFback;
XSegment SFsegs[2], SFcompletionSegs[2];
XawTextPosition SFtextPos;
int SFupperX, SFlowerY, SFupperY;
int SFtextX, SFtextYoffset;
int SFentryWidth, SFentryHeight;
int SFlineToTextH = 3;
int SFlineToTextV = 3;
int SFbesideText = 3;
int SFaboveAndBelowText = 2;
int SFcharsPerEntry = 15;
int SFlistSize = 10;
int SFworkProcAdded = 0;
XtAppContext SFapp;
int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
char SFtextBuffer[MAXPATHLEN];
XtIntervalId SFdirModTimerId;
int (*SFfunc) ();

static int SFstatus = SEL_FILE_NULL;

static Widget selFile, selFileCancel, selFileOK, selFilePrompt;
/* For file filter. */
static Widget selFileLabel, selFileMask, selFileHide;

#define MASKWIDTH 16
static char fileMask[MASKWIDTH + 2] = "*.dvi";

static Atom SFwmDeleteWindow;

static char *oneLineTextEditTranslations =
    "<Key>Return: redraw-display()\n"
    "Ctrl<Key>M: redraw-display()\n";

#if !defined (HAVE_STRERROR) && !defined (strerror)
static char *
strerror(int errnum)
{
    return 0 < errnum && errnum <= sys_nerr
      ? sys_errlist[errnum] : "Unknown system error";
}
#endif /* not HAVE_STRERROR && not strerror */

void
raise_file_selector(void)
{
    if (selFile != 0) {
      XRaiseWindow(DISP, XtWindow(selFile));
    }
}

static void
SFexposeList(Widget w, XtPointer n, XEvent *event, Boolean *cont)
{
    UNUSED(w);
    UNUSED(cont);
    
    if ((event->type == NoExpose) || event->xexpose.count) {
      return;
    }

    SFdrawList((int)n, SF_DO_NOT_SCROLL);
}

static void
SFmodVerifyCallback(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
{
    char buf[2];

    UNUSED(w);
    UNUSED(client_data);
    UNUSED(cont);
    
    if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
      ((*buf) == '\r')) {
      SFstatus = SEL_FILE_OK;
    }
    else {
      SFstatus = SEL_FILE_TEXT;
    }
}

static void
SFokCallback(Widget w, XtPointer cl, XtPointer cd)
{
    UNUSED(w);
    UNUSED(cl);
    UNUSED(cd);
    
    SFstatus = SEL_FILE_OK;
}

static XtCallbackRec SFokSelect[] = {
    {SFokCallback, (XtPointer) NULL},
    {NULL, (XtPointer) NULL},
};

static void
SFcancelCallback(Widget w, XtPointer cl, XtPointer cd)
{
    UNUSED(w);
    UNUSED(cl);
    UNUSED(cd);
    
    SFstatus = SEL_FILE_CANCEL;
}

static XtCallbackRec SFcancelSelect[] = {
    {SFcancelCallback, (XtPointer) NULL},
    {NULL, (XtPointer) NULL},
};

static void
SFdismissAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
    UNUSED(w);
    UNUSED(params);
    UNUSED(num_params);
    
    if (event->type == ClientMessage && (unsigned)(event->xclient.data.l[0]) != SFwmDeleteWindow)
      return;

    SFstatus = SEL_FILE_CANCEL;
}

static char *wmDeleteWindowTranslation = "<Message>WM_PROTOCOLS: SelFileDismiss()\n";

static XtActionsRec sf_actions[] = {
    {"SelFileDismiss", SFdismissAction},
};

/* Don't show files that don't get through the filter.  */

/* return 1 if file is masked (mask does not match filename), 0 otherwise */
static int
maskFile(const char *mask, char *filename)
{
    int c, c1;

    while ((c = *mask++)) {
      if (c == '*') {
          while ((c1 = *mask++)) {
            if (c1 != '*') {
                if (!(*filename))
                  return 1;
                if (c1 != '?') {
                  while ((filename = strchr(filename, c1))) {
                      if (!maskFile(mask, ++filename))
                        return 0;
                  }
                  return 1;
                }
                else
                  filename++;
            }
          }
          return 0;
      }
      if (c == '?') {
          if (!*filename)
            return 1;
      }
      else if (c != *filename)
          return 1;
      filename++;
    }
    return (*filename) ? 1 : 0;
}

Boolean hideFlag = False;
static int
showEntry(char *entryReal, char **entryShown, struct stat *statBuf)
{
    UNUSED(entryShown);

    if ((hideFlag && entryReal[0] == '.') || (!S_ISDIR(statBuf->st_mode) && maskFile(fileMask, entryReal)))
      return 0;
    entryReal[strlen(entryReal)] = SFstatChar(statBuf);
    return 1;
}

static void
maskChanged(Widget w, XtPointer client_data, XEvent *call_data, Boolean *cont)
{
    char buf[2];
    SFDir *dir;

    UNUSED(w);
    UNUSED(client_data);
    UNUSED(cont);
    
    if ((XLookupString((XKeyPressedEvent *)call_data, buf, 2, NULL, NULL) == 1) && ((*buf) == '\r')) {
      for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
          *(dir->dir) = 0;    /* force a re-read */
      SFupdatePath();
    }
}

static void
hideFiles(Widget w, XtPointer client_data, XtPointer call_data)
{
    SFDir *dir;
    SFEntry *entry;

    UNUSED(client_data);
    UNUSED(call_data);
    
    hideFlag = !hideFlag;
    if (hideFlag) {
      XtVaSetValues(w, XtNlabel, "hidden", NULL);
      for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
          if (!(dir->nEntries))
            continue;
          dir->vOrigin = 0;
          for (entry = &(dir->entries[dir->nEntries - 1]);
             entry >= dir->entries; entry--)
            entry->statDone = 0;
          SFdrawLists(SF_DO_SCROLL);
      }
    }
    else {
      XtVaSetValues(w, XtNlabel, "shown", NULL);
      for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
          *(dir->dir) = 0;    /* force a re-read */
      SFupdatePath();
    }
}


static Widget
SFcreateWidgets(Widget parent, const char *title, const char *prompt, const char *ok, const char *cancel)
{
    Cardinal i, n;
    int listWidth, listHeight;
    int listSpacing = 10;
    int scrollThickness = 15;
    int hScrollX, hScrollY;
    int vScrollX, vScrollY;
    Cursor xtermCursor, sbRightArrowCursor, arrowCursor;
    Arg arglist[20];
    Widget paned, box;
    
    i = 0;
    XtSetArg(arglist[i], XtNtransientFor, parent);
    XtSetArg(arglist[i], XtNtitle, title);
    i++;

    selFile = XtAppCreateShell("xdviSelFile", "XdviSelFile",
                         transientShellWidgetClass, SFdisplay,
                         arglist, i);

    /* Add WM_DELETE_WINDOW protocol */
    XtAppAddActions(XtWidgetToApplicationContext(selFile),
                sf_actions, XtNumber(sf_actions));
    XtOverrideTranslations(selFile,
                     XtParseTranslationTable(wmDeleteWindowTranslation));

    paned = XtVaCreateManagedWidget("paned", panedWidgetClass, selFile, NULL);
    i = 0;
    XtSetArg(arglist[i], XtNdefaultDistance, 6);
    i++;
    selFileForm = XtCreateManagedWidget("selFileForm",
                              formWidgetClass, paned, arglist, i);

    i = 0;
    XtSetArg(arglist[i], XtNlabel, prompt);
    i++;
    XtSetArg(arglist[i], XtNresizable, True);
    i++;
    XtSetArg(arglist[i], XtNtop, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNbottom, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNleft, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNright, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNborderWidth, 0);
    i++;
    XtSetArg(arglist[i], XtNvertDistance, 20);
    i++;
    selFilePrompt = XtCreateManagedWidget("selFilePrompt",
                                labelWidgetClass, selFileForm,
                                arglist, i);

#if 1
    i = 0;
    XtSetArg(arglist[i], XtNforeground, &SFfore);
    i++;
    XtSetArg(arglist[i], XtNbackground, &SFback);
    i++;
    XtGetValues(selFilePrompt, arglist, i);
#endif

    SFinitFont();

    SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth + SFbesideText;
    SFentryHeight = SFaboveAndBelowText + SFcharHeight + SFaboveAndBelowText;

    listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
      scrollThickness;
    listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
      SFlineToTextV + SFlistSize * SFentryHeight +
      SFlineToTextV + 1 + scrollThickness;

    SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;

    hScrollX = -1;
    hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
      SFlineToTextV + SFlistSize * SFentryHeight + SFlineToTextV;
    SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;

    vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
    vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
    SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
      SFlineToTextV;

    SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
    SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
      SFlineToTextV;
    SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
      SFlineToTextV + SFlistSize * SFentryHeight - 1;

    SFtextX = SFlineToTextH + SFbesideText;
    SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;

    SFsegs[0].x1 = 0;
    SFsegs[0].y1 = vScrollY;
    SFsegs[0].x2 = vScrollX - 1;
    SFsegs[0].y2 = vScrollY;
    SFsegs[1].x1 = vScrollX;
    SFsegs[1].y1 = 0;
    SFsegs[1].x2 = vScrollX;
    SFsegs[1].y2 = vScrollY - 1;

    SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
    SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
      SFlineToTextH + SFentryWidth - 1;

    i = 0;
/*     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4 - w - 10); */
    XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
    i++;
/*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*      i++; */

/*     XtSetArg(arglist[i], XtNfromHoriz, selFilePrompt); */
/*     i++; */
/*     XtSetArg(arglist[i], XtNhorizDistance, 10); */
    XtSetArg(arglist[i], XtNfromVert, selFilePrompt);
    i++;
/*      XtSetArg(arglist[i], XtNvertDistance, 0); */
/*      i++; */
    XtSetArg(arglist[i], XtNresizable, True);
    i++;
    XtSetArg(arglist[i], XtNtop, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNbottom, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNleft, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNright, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNstring, SFtextBuffer);
    i++;
    XtSetArg(arglist[i], XtNlength, MAXPATHLEN);
    i++;
    XtSetArg(arglist[i], XtNeditType, XawtextEdit);
    i++;
    XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);
    i++;
    XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);
    i++;
    XtSetArg(arglist[i], XtNuseStringInPlace, True);
    i++;
    XtSetArg(arglist[i], XtNvertDistance, 5);
    i++;
    selFileField = XtCreateManagedWidget("selFileField",
                                 asciiTextWidgetClass, selFileForm,
                                 arglist, i);

    XtOverrideTranslations(selFileField,
                     XtParseTranslationTable
                     (oneLineTextEditTranslations));
/*    XtSetKeyboardFocus(selFileForm, selFileField);
      need focus for selFileMask widget to set the filter */

    i = 0;
    XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
    i++;
    XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);
    i++;
    XtSetArg(arglist[i], XtNheight, scrollThickness);
    i++;
/*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*      i++; */
    XtSetArg(arglist[i], XtNfromVert, selFileField);
    i++;
    XtSetArg(arglist[i], XtNvertDistance, 30);
    i++;
    XtSetArg(arglist[i], XtNtop, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNbottom, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNleft, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNright, XtChainLeft);
    i++;
    selFileHScroll = XtCreateManagedWidget("selFileHScroll",
                                 scrollbarWidgetClass, selFileForm,
                                 arglist, i);

    XtAddCallback(selFileHScroll, XtNjumpProc,
              (XtCallbackProc)SFpathSliderMovedCallback, (XtPointer) NULL);
    XtAddCallback(selFileHScroll, XtNscrollProc,
              (XtCallbackProc)SFpathAreaSelectedCallback, (XtPointer) NULL);

    i = 0;
    XtSetArg(arglist[i], XtNwidth, listWidth);
    i++;
    XtSetArg(arglist[i], XtNheight, listHeight);
    i++;
/*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*      i++; */
    XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
    i++;
    XtSetArg(arglist[i], XtNvertDistance, 10);
    i++;
    XtSetArg(arglist[i], XtNtop, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNbottom, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNleft, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNright, XtChainLeft);
    i++;
    selFileLists[0] = XtCreateManagedWidget("selFileList1",
                                  compositeWidgetClass, selFileForm,
                                  arglist, i);

    i = 0;
    XtSetArg(arglist[i], XtNwidth, listWidth);
    i++;
    XtSetArg(arglist[i], XtNheight, listHeight);
    i++;
/*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*      i++; */
    XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);
    i++;
    XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
    i++;
    XtSetArg(arglist[i], XtNhorizDistance, listSpacing);
    i++;
    XtSetArg(arglist[i], XtNvertDistance, 10);
    i++;
    XtSetArg(arglist[i], XtNtop, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNbottom, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNleft, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNright, XtChainLeft);
    i++;
    selFileLists[1] = XtCreateManagedWidget("selFileList2",
                                  compositeWidgetClass, selFileForm,
                                  arglist, i);

    i = 0;
    XtSetArg(arglist[i], XtNwidth, listWidth);
    i++;
    XtSetArg(arglist[i], XtNheight, listHeight);
    i++;
/*      XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*      i++; */
    XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);
    i++;
    XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
    i++;
    XtSetArg(arglist[i], XtNhorizDistance, listSpacing);
    i++;
    XtSetArg(arglist[i], XtNvertDistance, 10);
    i++;
    XtSetArg(arglist[i], XtNtop, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNbottom, XtChainTop);
    i++;
    XtSetArg(arglist[i], XtNleft, XtChainLeft);
    i++;
    XtSetArg(arglist[i], XtNright, XtChainLeft);
    i++;
    selFileLists[2] = XtCreateManagedWidget("selFileList3",
                                  compositeWidgetClass, selFileForm,
                                  arglist, i);

    for (n = 0; n < 3; n++) {

      i = 0;
      XtSetArg(arglist[i], XtNx, vScrollX);
      i++;
      XtSetArg(arglist[i], XtNy, vScrollY);
      i++;
      XtSetArg(arglist[i], XtNwidth, scrollThickness);
      i++;
      XtSetArg(arglist[i], XtNheight, SFvScrollHeight);
      i++;
/*    XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*    i++; */
      selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
                                       scrollbarWidgetClass,
                                       selFileLists[n], arglist, i);

      XtAddCallback(selFileVScrolls[n], XtNjumpProc,
                  (XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer) n);
      XtAddCallback(selFileVScrolls[n], XtNscrollProc,
                  (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer) n);

      i = 0;

      XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
      i++;
      XtSetArg(arglist[i], XtNx, hScrollX);
      i++;
      XtSetArg(arglist[i], XtNy, hScrollY);
      i++;
      XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);
      i++;
      XtSetArg(arglist[i], XtNheight, scrollThickness);
      i++;
/*    XtSetArg(arglist[i], XtNborderColor, SFfore); */
/*    i++; */
      selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
                                       scrollbarWidgetClass,
                                       selFileLists[n], arglist, i);

      XtAddCallback(selFileHScrolls[n], XtNjumpProc,
                  (XtCallbackProc)SFhSliderMovedCallback, (XtPointer) n);
      XtAddCallback(selFileHScrolls[n], XtNscrollProc,
                  (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer) n);
    }

    /* Do the file filter stuff.  */
    selFileLabel = XtVaCreateManagedWidget("selFileLabel",
                                 labelWidgetClass, selFileForm,
                                 XtNfromVert, selFileLists[0],
                                 XtNvertDistance, 30,
/*                               XtNfromHoriz, selFileCancel, */
/*                               XtNhorizDistance, 60, */
                                 XtNlabel, "File Mask:",
                                 XtNborderWidth, 0,
                                 XtNtop, XtChainTop,
                                 XtNbottom, XtChainTop, NULL);

    selFileMask = XtVaCreateManagedWidget("selFileMask",
                                asciiTextWidgetClass, selFileForm,
                                XtNwidth, MASKWIDTH / 2 * SFcharWidth,
                                XtNfromVert, selFileLists[0],
                                XtNvertDistance, 30,
                                XtNfromHoriz, selFileLabel,
                                XtNhorizDistance, 0,
                                XtNtop, XtChainTop,
                                XtNbottom, XtChainTop,
                                XtNstring, fileMask,
                                XtNlength, MASKWIDTH,
                                XtNeditType, XawtextEdit,
                                XtNwrap, XawtextWrapNever,
                                XtNuseStringInPlace, True, NULL);

    for (i = 0; i < 3; i++)
      XtSetKeyboardFocus(selFileLists[i], selFileField);

    XtOverrideTranslations(selFileMask,
                     XtParseTranslationTable
                     (oneLineTextEditTranslations));

    XtAddEventHandler(selFileMask, KeyPressMask, False,
                  (XtEventHandler)maskChanged, (XtPointer) NULL);

    selFileLabel = XtVaCreateManagedWidget("selFileLabel",
                                 labelWidgetClass, selFileForm,
                                 XtNfromVert, selFileLists[0],
                                 XtNvertDistance, 30,
                                 XtNfromHoriz, selFileMask,
                                 XtNhorizDistance, 40,
                                 XtNlabel, "Dot files are:",
                                 XtNborderWidth, 0,
                                 XtNtop, XtChainTop,
                                 XtNbottom, XtChainTop, NULL);

    selFileHide = XtVaCreateManagedWidget("selFileHide",
                                commandWidgetClass, selFileForm,
/*                              XtNwidth, 7 * SFcharWidth, */
                                XtNfromVert, selFileLists[0],
                                XtNvertDistance, 30,
                                XtNfromHoriz, selFileLabel,
                                XtNhorizDistance, 2,
                                XtNlabel, hideFlag ? "hidden" : "shown",
/*                              XtNborderWidth, 1, */
                                XtNtop, XtChainTop,
/*                              XtNjustify, XtJustifyLeft, */
                                XtNbottom, XtChainTop,
                                NULL);
    XtAddCallback(selFileHide, XtNcallback, (XtCallbackProc)hideFiles, NULL);

    box = XtVaCreateManagedWidget("box", formWidgetClass,
                          paned,
                          XtNshowGrip, False,
                          XtNdefaultDistance, 6,
                          XtNskipAdjust, True,
                          XtNaccelerators, G_accels_cr,
                          NULL);
    selFileOK = XtVaCreateManagedWidget("selFileOK", commandWidgetClass,
                              box,
                              XtNlabel, ok,
                              XtNcallback, SFokSelect,
                              XtNtop, XtChainTop,
                              XtNbottom, XtChainBottom,
                              XtNleft, XtChainLeft,
                              XtNright, XtChainLeft,
                              NULL);
    selFileCancel = XtVaCreateManagedWidget("selFileCancel", commandWidgetClass,
                                  box,
                                  XtNlabel, cancel,
                                  XtNcallback, SFcancelSelect,
/*                                XtNborderColor, SFfore, */
                                  XtNfromHoriz, selFileOK,
                                  XtNbottom, XtChainBottom,
                                  XtNleft, XtChainRight,
                                  XtNright, XtChainRight,
                                  NULL);

    XtSetMappedWhenManaged(selFile, False);
    XtRealizeWidget(selFile);

    /* Add WM_DELETE_WINDOW protocol */
    SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);

    SFcreateGC();

    xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);

    sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
    arrowCursor = XCreateFontCursor(SFdisplay, XC_left_ptr);

    XDefineCursor(SFdisplay, XtWindow(selFileForm), arrowCursor);
    XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);

    for (n = 0; n < 3; n++) {
      XDefineCursor(SFdisplay, XtWindow(selFileLists[n]), sbRightArrowCursor);
    }
    XDefineCursor(SFdisplay, XtWindow(selFileOK), arrowCursor);
    XDefineCursor(SFdisplay, XtWindow(selFileCancel), arrowCursor);

    for (n = 0; n < 3; n++) {
      XtAddEventHandler(selFileLists[n], ExposureMask, True,
                    (XtEventHandler)SFexposeList, (XtPointer) n);
      XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
                    (XtEventHandler)SFenterList, (XtPointer) n);
      XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
                    (XtEventHandler)SFleaveList, (XtPointer) n);
      XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
                    (XtEventHandler)SFmotionList, (XtPointer) n);
      XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
                    (XtEventHandler)SFbuttonPressList, (XtPointer) n);
      XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
                    (XtEventHandler)SFbuttonReleaseList, (XtPointer) n);
    }

    XtAddEventHandler(selFileField, KeyPressMask, False,
                  (XtEventHandler)SFmodVerifyCallback, (XtPointer) NULL);

    SFapp = XtWidgetToApplicationContext(selFile);
    return selFile;
}

/* position widget under the cursor */
void
SFpositionWidget(Widget w)
{
    Arg args[3];
    Cardinal num_args;
    Dimension width, height, b_width;
    int x, y, max_x, max_y;
    Window root, child;
    int dummyx, dummyy;
    unsigned int dummymask;

    XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
              &dummyx, &dummyy, &dummymask);
    num_args = 0;
    XtSetArg(args[num_args], XtNwidth, &width);
    num_args++;
    XtSetArg(args[num_args], XtNheight, &height);
    num_args++;
    XtSetArg(args[num_args], XtNborderWidth, &b_width);
    num_args++;
    XtGetValues(w, args, num_args);

    width += 2 * b_width;
    height += 2 * b_width;

    x -= ((Position) width / 2);
    if (x < 0)
      x = 0;
    if (x > (max_x = (Position) (XtScreen(w)->width - width)))
      x = max_x;

    y -= ((Position) height / 2);
    if (y < 0)
      y = 0;
    if (y > (max_y = (Position) (XtScreen(w)->height - height)))
      y = max_y;

    num_args = 0;
    XtSetArg(args[num_args], XtNx, x);
    num_args++;
    XtSetArg(args[num_args], XtNy, y);
    num_args++;
    XtSetValues(w, args, num_args);
}


FILE *
SFopenFile(const char *name, const char *mode, const char *prompt, const char *failed)
{
    Arg args[1];
    FILE *fp;

    UNUSED(args);
    UNUSED(prompt);
    UNUSED(failed);
    
    SFchdir(SFstartDir);
    errno = 0;
    if (!name || *name == 0 || (fp = XFOPEN(name, mode)) == NULL) {
      XBell(DISP, 0);
      return NULL;
    }
    return fp;
}

void
SFtextChanged(void)
{
    if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
      (void)strcpy(SFcurrentPath, SFtextBuffer);

      SFtextPos = XawTextGetInsertionPoint(selFileField);
    }
    else {
      (void)strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);

      SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
    }

    if (!SFworkProcAdded) {
      (void)XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
      SFworkProcAdded = 1;
    }

    SFupdatePath();
}

static void
SFprepareToReturn(void)
{
    SFstatus = SEL_FILE_NULL;
    /* XtRemoveGrab(selFile); */
    XtUnmapWidget(selFile);

    if (SFdirModTimerId) {
      XtRemoveTimeOut(SFdirModTimerId);
      SFdirModTimerId = 0;
    }
    if (SFchdir(SFstartDir)) {
      XtAppError(SFapp, "XsraSelFile: can't return to current directory");
    }
}

void
XsraSelFile(Widget parent, struct filesel_callback *callback)
/*        const char *title, const char *prompt, */
/*        const char *ok, const char *cancel, */
/*        const char *init_path, */
/*        const char *mask, */
/*        Boolean must_exist, */
/*        Widget *ret_widget */
{
    static Boolean firstTime = True;
    Widget w;
    Cardinal i;
    Arg arglist[20];
    XEvent event;
    
    if (!callback->prompt) {
      callback->prompt = "Pathname:";
    }

    if (!callback->title) {
      callback->title = "Xdvi: select filename";
    }

    if (!callback->ok) {
      callback->ok = "OK";
    }

    if (!callback->cancel) {
      callback->cancel = "Cancel";
    }

    if (firstTime) {
      firstTime = False;
      SFdisplay = XtDisplay(parent);
      w = SFcreateWidgets(parent, callback->title, callback->prompt, callback->ok, callback->cancel);
    }
    else {
      i = 0;
      XtSetArg(arglist[i], XtNlabel, callback->prompt);
      i++;
      XtSetValues(selFilePrompt, arglist, i);

      i = 0;
      XtSetArg(arglist[i], XtNlabel, callback->ok);
      i++;
      XtSetValues(selFileOK, arglist, i);

      i = 0;
      XtSetArg(arglist[i], XtNlabel, callback->cancel);
      i++;
      XtSetValues(selFileCancel, arglist, i);
    }

    SFpositionWidget(selFile);
    XtMapWidget(selFile);

    {
      char *cwd = xgetcwd();
      strcpy(SFstartDir, cwd);
      free(cwd);
    }
    if (SFstartDir[0] == 0) {
      XtAppError(SFapp, "XsraSelFile: can't get current directory");
    }
    (void)strcat(SFstartDir, "/");
    (void)strcpy(SFcurrentDir, SFstartDir);

    if (callback->init_path) {
      if (callback->init_path[0] == '/') {
          (void)strcpy(SFcurrentPath, callback->init_path);
          if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
            SFsetText(SFcurrentPath);
          }
          else {
            SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
          }
      }
      else {
          (void)strcat(strcpy(SFcurrentPath, SFstartDir), callback->init_path);
          SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
      }
    }
    else {
      SFsetText(SFcurrentDir);
      (void)strcpy(SFcurrentPath, SFstartDir);
    }

    SFfunc = showEntry;

    SFtextChanged();

    /* don't grab the pointer so that warning popups still work */
    /* XtAddGrab(selFile, True, True); */

    SFdirModTimerId = XtAppAddTimeOut(SFapp, 1200UL,
                              SFdirModTimer, (XtPointer) NULL);
    
    if (strcmp(fileMask, callback->filemask) != 0) { /* if mask changed */
      SFDir *dir;
      strncpy(fileMask, callback->filemask, MASKWIDTH);
      XtVaSetValues(selFileMask, XtNstring, fileMask, NULL);
      for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
          *(dir->dir) = 0;    /* force a re-read */
      SFupdatePath();
    }

    while (1) {
      XtAppNextEvent(SFapp, &event);
      switch (event.type) {
          Widget w;
#if 0 /* don't do this, it may send the X server into a busy loop if the File selector
       is positioned over a window that is `on top' by default */
      case Expose:
          if (!raise_message_windows())
            raise_file_selector();
          break;
#endif
      case KeyPress:
      case ButtonPress:
          /* beep if keypress was inside main window */
          w = XtWindowToWidget(DISP, event.xany.window);
          while ((w != NULL) && (w != selFile)) {
            /* exception: message windows */
            if (is_message_window(w))
                break;
            w = XtParent(w);
          }
          if (w == NULL || w == globals.widgets.top_level) {
            XBell(DISP, 0);
          }
          break;
      }

      XtDispatchEvent(&event);

      switch (SFstatus) {
      case SEL_FILE_TEXT:
          SFstatus = SEL_FILE_NULL;
          SFtextChanged();
          break;
      case SEL_FILE_OK:
          if (callback->must_exist) {
            FILE *tmp_fp = XFOPEN(SFtextBuffer, "r");
            dviErrFlagT errflag = NO_ERROR;
            if (tmp_fp == NULL) {
                popup_message(selFile,
                          MSG_ERR, NULL, "Could not open %s: %s.\n",
                          SFtextBuffer, strerror(errno));
                SFstatus = SEL_FILE_NULL;
                break;
            }
            else if (!process_preamble(tmp_fp, &errflag)
                   || !find_postamble(tmp_fp, &errflag)
                   || !read_postamble(tmp_fp, &errflag, False)) {
                popup_message(selFile,
                          MSG_ERR, NULL, "Error opening %s:\n%s.",
                          SFtextBuffer, get_dvi_error(errflag));
                fclose(tmp_fp);
                SFstatus = SEL_FILE_NULL;
                break;
            }
            else { /* file is OK */
                fclose(tmp_fp);
                SFprepareToReturn();
                callback->func_ptr(SFtextBuffer, callback->data);
                return;
/*              return xstrdup(SFtextBuffer); */
            }
          }
          else {
            SFprepareToReturn();
            callback->func_ptr(SFtextBuffer, callback->data);
            return;
/*          return xstrdup(SFtextBuffer); */
          }
      case SEL_FILE_CANCEL:
          SFprepareToReturn();
          if (callback->exit_on_cancel)
            exit(0);
          return;
/*        return NULL; */
      case SEL_FILE_NULL:
          break;
      }
    }
}

#else
/* silence `empty compilation unit' warnings */
static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
#endif /* !defined(MOTIF) */

Generated by  Doxygen 1.6.0   Back to index