Logo Search packages:      
Sourcecode: felt version File versions  Download package

filedialog.c

/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/************************************************************************
 * File:    filedialog.c                                    *
 *                                                    *
 * Description: This file contains the private and public function and  *
 *          type definitions for the file file dialog box.        *
 ************************************************************************/

# include <stdio.h>
# include <X11/Xos.h>
# include <sys/stat.h>
# include <pwd.h>
# include <dirent.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <X11/Shell.h>
# include <X11/Xaw/AsciiText.h>
# include <X11/Xaw/Command.h>
# include <X11/Xaw/Label.h>
# include <X11/Xaw/List.h>
# include <X11/Xaw/Viewport.h>
# include <X11/Xaw/Toggle.h>
# include "Layout.h"
# include "FileDialog.h"
# include "TabGroup.h"
# include "scroll.h"
# include "util.h"

# ifndef X_NOT_STDC_ENV
# include <stdlib.h>
# else
extern char *getenv ( );
# endif

# define MaxEntries 2048
# define MaxPathLen 2048

# define Waiting   0
# define Canceled -1
# define Okayed    1

struct file_dialog {
    Widget     shell;         /* transientShell  <specified>        */
    Widget     layout;        /*    Layout  layout            */
    Widget     label;         /*         Label  label   */
    Widget     directory;           /*         Label  directory     */
    Widget     entry;         /*         AsciiText  entry     */
    Widget     viewport;            /*         Viewport  viewport   */
    Widget     list;          /*            List  list        */
    Widget         toggle1;         /*         Toggle  toggle1      */
    Widget         toggle2;         /*         Toggle  toggle2      */
    Widget         toggle1_name;    /*         Toggle  toggle1_name */
    Widget         toggle2_name;    /*         Toggle  toggle2_name */
    Widget     okay;          /*         Command  okay        */
    Widget     cancel;        /*         Command  cancel      */
    String     path;
    String     displayed;
    XtCallbackProc callback;
    XtPointer        client_data;
    int              status;
};


/* Resources */

static Pixel highlight;

static String dummy_list [ ] = {
    "                              ", "", "", "", "", "", "", "", "", "", NULL
};

static char layout_string [ ] =
"vertical { 4 \
 horizontal { 4 label <+inf -100% *> 4 } 4 \
 horizontal { 4 directory <+inf -100% *> 4 } 4 \
 horizontal { 4 entry <+inf -100% *> 4 } 4 \
 horizontal { 4 viewport <+inf -100% * +inf -100%> 4 } 4 \
 horizontal { 4 toggle1 2 toggle1_name 4 <+inf -100%> \
                toggle2 2 toggle2_name 4 } 4 \
 horizontal { 4 okay 4 <+inf -100%> cancel 4 } 4 }";

static Arg color_args [ ] = {
    {XtNborderColor, (XtArgVal) &highlight},
};

static Arg layout_args [ ] = {
    {XtNlayout, (XtArgVal) NULL},
};

static Arg label_args [ ] = {
    {XtNresize,      (XtArgVal) True},
    {XtNjustify,     (XtArgVal) XtJustifyLeft},
    {XtNborderWidth, (XtArgVal) 0},
};

static Arg directory_args [ ] = {
    {XtNresize,      (XtArgVal) True},
    {XtNjustify,     (XtArgVal) XtJustifyLeft},
    {XtNborderWidth, (XtArgVal) 0},
};

static Arg entry_args [ ] = {
    {XtNresize,      (XtArgVal) XawtextResizeWidth},
    {XtNeditType,    (XtArgVal) XawtextEdit},
    {XtNborderWidth, (XtArgVal) 0},
};

static Arg viewport_args [ ] = {
    {XtNallowVert,   (XtArgVal) True},
    {XtNuseRight,    (XtArgVal) True},
    {XtNforceBars,   (XtArgVal) True},
    {XtNborderWidth, (XtArgVal) 0},
};

static Arg list_args [ ] = {
    {XtNdefaultColumns, (XtArgVal) 1},
    {XtNforceColumns,   (XtArgVal) 1},
    {XtNresize,         (XtArgVal) True},
    {XtNlist,           (XtArgVal) dummy_list},
};

static Arg name_args [ ] = {
    {XtNlabel,       (XtArgVal) ""},
    {XtNborderWidth, (XtArgVal) 0},
};

static Arg toggle_args [ ] = {
    {XtNlabel,         (XtArgVal) " "},
};

/* Translation tables */

static String entry_table =
"<Key>Return:   FileDialogOkay()\n\
 <Key>Escape:   FileDialogCancel()\n\
 <Btn1Down>:    SetFocus() select-start()";

static XtTranslations entry_translations;

static String viewport_table =
"<Key>Return:   FileDialogOkay()\n\
 <Key>Escape:   FileDialogCancel()\n\
 <Btn1Down>:    SetFocus()";

static XtTranslations viewport_translations;

static String list_table =
"<Btn1Down>(2): Set() Notify() FileDialogOkay()\n\
 <Btn1Down>:    Set() Notify()\n\
 <Btn2Down>:    Set() Notify() FileDialogOkay()";

static XtTranslations list_translations;

static String okay_table =
"<Key>Return:   AutoRepeat(off) set()\n\
 <KeyUp>Return: AutoRepeat(saved) notify() unset()\n\
 <Key>space:    AutoRepeat(off) set()\n\
 <KeyUp>space:  AutoRepeat(saved) notify() unset()\n\
 <Key>Escape:   FileDialogCancel()";

static XtTranslations okay_translations;

static String cancel_table =
"<Key>Return:   AutoRepeat(off) set()\n\
 <KeyUp>Return: AutoRepeat(saved) notify() unset()\n\
 <Key>space:    AutoRepeat(off) set()\n\
 <KeyUp>space:  AutoRepeat(saved) notify() unset()\n\
 <Key>Escape:   FileDialogCancel()";

static XtTranslations cancel_translations;

static String toggle_table = 
"<Key>Return: FileDialogOkay()\n\
 <Key>Escape: FileDialogCancel()\n\
 <Key>space:  toggle() notify()";

static XtTranslations toggle_translations;


/************************************************************************
 * Function:      DisplayPath                               *
 *                                                    *
 * Description:   Displays the path of the current directory by possibly      *
 *          shortening the directory at the front so that it fits.      *
 ************************************************************************/

static void DisplayPath (filed, width)
    FileDialog filed;
    Dimension  width;
{
    Arg            args [1];
    int            length;
    String   ptr;
    XFontStruct   *font;


    /* Retrieve the width if necessary. */

    if (width == 0) {
      XtSetArg (args [0], XtNwidth, &width);
      XtGetValues (filed -> directory, args, 1);
    }


    /* Retrieve the font. */

    XtSetArg (args [0], XtNfont, &font);
    XtGetValues (filed -> directory, args, 1);


    /* Prepare to shorten string so that it will fit. */

    length = strlen (filed -> path);
    ptr = filed -> path;

    width -= GetTextWidth (font, "...", 3) + 4;


    /* Keep shortening the string until it fits. */

    while (GetTextWidth (font, ptr, length) > width && length > 1) {
      ptr ++;
      length --;
    }


    /* Display the possibly shortened string. */

    if (ptr != filed -> path)
      sprintf (filed -> displayed, "...%s", ptr);
    else
      strcpy (filed -> displayed, filed -> path);

    XtSetArg (args [0], XtNlabel, filed -> displayed);
    XtSetValues (filed -> directory, args, 1);
}


/************************************************************************
 * Function:      ResizeHandler                                   *
 *                                                    *
 * Description:   Event handler called upon StructureNotify events.  If *
 *          the event is specifically a ConfigureNotify event then      *
 *          the path to the current directory is redisplayed within     *
 *          the new window size.  (We subtract 8 to account for the     *
 *          4 pixel space between the label width and the edge of *
 *          the shell window; we use an event handler rather than a     *
 *          translation so that we can pass the file dialog as    *
 *          client data.                                    *
 ************************************************************************/

static void ResizeHandler (w, client_data, event, cont)
    Widget    w;
    XtPointer client_data;
    XEvent   *event;
    Boolean  *cont;
{
    if (event -> type == ConfigureNotify)
      DisplayPath ((FileDialog) client_data, event -> xconfigure.width - 8);
}


/************************************************************************
 * Function:      SortEntries                               *
 *                                                    *
 * Description:   Used by qsort() to compare two strings; directories   *
 *          (which end with a /) are always placed before files   *
 ************************************************************************/

static int SortEntries (s1, s2)
    String *s1;
    String *s2;
{
    String dir1;
    String dir2;


    dir1 = strchr (*s1, '/');
    dir2 = strchr (*s2, '/');

    if (dir1 != NULL && dir2 == NULL)
      return -1;

    if (dir1 == NULL && dir2 != NULL)
      return 1;

    return strcmp (*s1, *s2);
}


/************************************************************************
 * Function:      ReadDirectory                                   *
 *                                                    *
 * Description:   Reads the entries of the specified directory, sorts the     *
 *          entries, and updates the associated list widget with  *
 *          the entries.  Directories are placed before files in  *
 *          sorted order and directory names end with a /.  If the      *
 *          directory cannot be opened, False is returned.        *
 *          Otherwise, True is returned.                    *
 ************************************************************************/

static Boolean ReadDirectory (filed, name)
    FileDialog filed;
    String     name;
{
    int              count;
    DIR             *dirp;
    struct stat      buf;
    struct dirent *entry;
    static String  list [MaxEntries] = {NULL};
    char       buffer [MaxPathLen];


    if ((dirp = opendir (name)) == NULL)
      return False;

    count = 0;
    while ((entry = readdir (dirp)) != NULL && count < MaxEntries) {
      if (!strcmp (entry -> d_name, "."))
          continue;

      XtFree (list [count]);
      sprintf (buffer, "%s/%s", name, entry -> d_name);
      if (!stat (buffer, &buf) && S_ISDIR (buf.st_mode)) {
          sprintf (buffer, "%s/", entry -> d_name);
          list [count ++] = XtNewString (buffer);
      } else
          list [count ++] = XtNewString (entry -> d_name);
    }

    closedir (dirp);
    qsort (list, count, sizeof (String), SortEntries);

    XawListChange (filed -> list, list, count, 0, True);
    XawViewportSetCoordinates (filed -> viewport, 0, 0);
    return True;
}


/************************************************************************
 * Function:      CopySelected                                    *
 *                                                    *
 * Description:   A callback for the List widget which copies the current     *
 *          entry to the entry widget.                      *
 ************************************************************************/

static void CopySelected (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    FileDialog           filed;
    XawListReturnStruct *info;


    filed = (FileDialog) client_data;
    info = (XawListReturnStruct *) call_data;
    SetTextString (filed -> entry, info -> string);
}


/************************************************************************
 * Function:      Okay                                      *
 *                                                    *
 * Description:   A callback for the okay button which forms a path name      *
 *          from the directory and current entry.  If the entry   *
 *          is an absolute path (begins with / or ~) then the     *
 *          current directory is ignored.  The path name is then  *
 *          normalized (removing .., //, and ~).  If the path names     *
 *          a file then that file is selected.  Otherwise, the path     *
 *          is used as a directory which is then read.            *
 ************************************************************************/

static void Okay (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    char       old;
    char       buffer [MaxPathLen];
    Arg              args   [1];
    String     dest;
    String     string;
    String     ptr;
    FileDialog       filed;
    struct passwd *entry;


    filed = (FileDialog) client_data;

    XtSetArg (args [0], XtNstring, &string);
    XtGetValues (filed -> entry, args, 1);


    /* If the entry is absolute ignore the current directory.  Otherwise,
       concatenate the entry and directory to form the new path. */

    if (string [0] == '/' || string [0] == '~')
      strcpy (buffer, string);
    else {
      strcpy (buffer, filed -> path);
      strcat (buffer, string);
    }


    /* Expand the tilde. */

    ptr = buffer;
    dest = filed -> path;

    if (!strncmp (buffer, "~/", 2) || !strcmp (buffer, "~")) {
      strcpy (dest, getenv ("HOME"));
      dest += strlen (dest);
      ptr ++;

    } else if (buffer [0] == '~') {
      while (*ptr && *ptr != '/')
          ptr ++;

      old = *ptr;
      *ptr = 0;

      if ((entry = getpwnam (buffer + 1)) != NULL) {
          strcpy (dest, entry -> pw_dir);
          dest += strlen (dest);
          *ptr = old;
      } else
          ptr = buffer;
    }


    /* Finish normalizing the directory entry removing any .. or //. */

    while (*ptr) {
      if (!strncmp (ptr, "//", 2) || !strcmp (ptr, "/"))
          ptr ++;

      else if (!strncmp (ptr, "/../", 4) || !strcmp (ptr, "/..")) {
          while (dest != filed -> path && *dest != '/')
            dest --;
          ptr +=3;

      } else
          *dest ++ = *ptr ++;

      *dest = 0;
    }

    if (filed -> path [0] == 0)
      strcpy (filed -> path, "/");


    /* Try to read the normalized path as a directory. */

    if (ReadDirectory (filed, filed -> path) == True) {


      /* Indicate the new directory and an empty entry. */

      if (strcmp (filed -> path, "/"))
          strcat (filed -> path, "/");

      DisplayPath (filed, 0);
        SetTextString (filed -> entry, "");


    /* A file was selected.  If this is the initial suggestion then decompose
       the suggestion into a directory and file name and use them. */

    } else if (call_data != NULL) {
      ptr = strrchr (filed -> path, '/');

        SetTextString (filed -> entry, ptr + 1);

      ptr [1] = 0;
      DisplayPath (filed, 0);
      ReadDirectory (filed, filed -> path);


    /* A file was selected.  Call the callback or set the
       selected flag, whichever is appropriate. */

    } else if (filed -> callback != NULL)
      filed -> callback (filed -> entry, filed -> client_data, filed -> path);

    else
      filed -> status = Okayed;
}

/************************************************************************
 * Function:      CheckToggle                               *
 *                                                    *
 * Description:                                                   *
 ************************************************************************/

static void CheckToggle (w, client_data, call_data)
    Widget  w;
    XtPointer   client_data;
    XtPointer   call_data;
{
    FileDialog          filed;
    Boolean       state;
    Arg                 args [1];

    filed = (FileDialog) client_data;

    XtSetArg (args [0], XtNstate, &state);
    XtGetValues (w, args, 1);

    if (state) {
       XtSetArg (args [0], XtNstate, False);
       if (w == filed -> toggle1)
          XtSetValues (filed -> toggle2, args, 1);
       else
          XtSetValues (filed -> toggle1, args, 1);
    }
    else {
       XtSetArg (args [0], XtNstate, True);
       XtSetValues (w, args, 1);
    }
}

/************************************************************************
 * Function:      Cancel                                          *
 *                                                    *
 * Description:   A callback for the cancel button which indicates that *
 *          the file dialog has been canceled by either calling the     *
 *          registered callback with a NULL string or by setting  *
 *          the canceled flag.                              *
 ************************************************************************/

static void Cancel (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    FileDialog filed;


    filed = (FileDialog) client_data;

    if (filed -> callback != NULL)
      filed -> callback (filed -> entry, filed -> client_data, NULL);
    else
      filed -> status = Canceled;
}


/************************************************************************
 * Function:      FileDialogOkay                                  *
 *                                                    *
 * Description:   An action procedure which emulates pressing of the okay     *
 *          button.                                         * 
 ************************************************************************/

static void FileDialogOkay (w, event, params, num_params)
    Widget   w;
    XEvent  *event;
    String  *params;
    Cardinal num_params;
{
    if (XtClass (w) == listWidgetClass)
      w = XtParent (w);

    w = XtNameToWidget (XtParent (w), "okay");
    XtCallCallbacks (w, XtNcallback, NULL);
}


/************************************************************************
 * Function:      FileDialogCancel                          *
 *                                                    *
 * Description:   An action procedure which emulates pressing of the    *
 *          cancel button.                                  *
 ************************************************************************/

static void FileDialogCancel (w, event, params, num_params)
    Widget   w;
    XEvent  *event;
    String  *params;
    Cardinal num_params;
{
    if (event -> type == ClientMessage)
      w = XtNameToWidget (w, "layout.cancel");
    else
      w = XtNameToWidget (XtParent (w), "cancel");

    XtCallCallbacks (w, XtNcallback, NULL);
}


/************************************************************************
 * Function:      FileDialogCreate                          *
 *                                                    *
 * Description:   Creates and returns a new file dialog box.  The dialog      *
 *          can be popped up using FileDialogSelect() which forces      *
 *          the user to make a selection, or by using FileDialog- *
 *          Popup() which will call a callback when a file is     *
 *          selected or the dialog is canceled.  The dialog can   *
 *          then be popped down using FileDialogPopdown().        *
 ************************************************************************/

FileDialog FileDialogCreate (parent, name, toggle_labels)
    Widget parent;
    String name;
    char   **toggle_labels;
{
    Arg                 args [1];
    Widget        group [6];
    unsigned            group_count;
    unsigned            mask;
    FileDialog          filed;
    static XtAppContext app_context = NULL;
    static XtActionsRec actions [ ] =
                  {{"FileDialogOkay",   FileDialogOkay},
                   {"FileDialogCancel", FileDialogCancel}};


    /* Perform one time initialization. */

    if (app_context == NULL) {
      app_context = XtWidgetToApplicationContext (parent);
      XtAppAddActions (app_context, actions, XtNumber (actions));
      AddAutoRepeatAction (app_context);

      layout_args [0].value = StringToLayout (parent, layout_string);

      entry_translations    = XtParseTranslationTable (entry_table);
      viewport_translations = XtParseTranslationTable (viewport_table);
      list_translations     = XtParseTranslationTable (list_table);
      okay_translations     = XtParseTranslationTable (okay_table);
      cancel_translations   = XtParseTranslationTable (cancel_table);
        toggle_translations   = XtParseTranslationTable (toggle_table);
    }


    /* Create the file dialog and its widgets. */

    filed = XtNew (struct file_dialog);

    filed -> path      = (String) XtMalloc (MaxPathLen);

    filed -> displayed = (String) XtMalloc (MaxPathLen);

    filed -> shell     = XtCreatePopupShell (name,
                   transientShellWidgetClass, parent,
                   NULL, 0);

    filed -> layout    = XtCreateManagedWidget ("layout",
                   layoutWidgetClass, filed -> shell,
                   layout_args, XtNumber (layout_args));

    filed -> label     = XtCreateManagedWidget ("label",
                   labelWidgetClass, filed -> layout,
                   label_args, XtNumber (label_args));

    filed -> directory = XtCreateManagedWidget ("directory",
                   labelWidgetClass, filed -> layout,
                   directory_args, XtNumber (directory_args));

    filed -> entry     = XtCreateManagedWidget ("entry",
                   asciiTextWidgetClass, filed -> layout,
                   entry_args, XtNumber (entry_args));

    filed -> viewport  = XtCreateManagedWidget ("viewport",
                   viewportWidgetClass, filed -> layout, 
                   viewport_args, XtNumber (viewport_args));

    filed -> list      = XtCreateManagedWidget ("list",
                   listWidgetClass, filed -> viewport,
                   list_args, XtNumber (list_args));
 
    filed -> okay      = XtCreateManagedWidget ("okay",
                   commandWidgetClass, filed -> layout,
                   NULL, 0);

    filed -> cancel    = XtCreateManagedWidget ("cancel",
                   commandWidgetClass, filed -> layout,
                   NULL, 0);

    if (toggle_labels != NULL) {
       filed -> toggle1   = XtCreateManagedWidget ("toggle1",
                            toggleWidgetClass, filed -> layout,
                            toggle_args, XtNumber (toggle_args));

       name_args [0].value = (XtArgVal) toggle_labels [0];
       filed -> toggle1_name = XtCreateManagedWidget ("toggle1_name", 
                               labelWidgetClass, filed -> layout, name_args, 
                               XtNumber (name_args));

       filed -> toggle2   = XtCreateManagedWidget ("toggle2",
                            toggleWidgetClass, filed -> layout,
                            toggle_args, XtNumber (toggle_args));

       name_args [0].value = (XtArgVal) toggle_labels [1];
       filed -> toggle2_name = XtCreateManagedWidget ("toggle2_name", 
                               labelWidgetClass, filed -> layout, name_args, 
                               XtNumber (name_args));
    }
    else {
       filed -> toggle1 = NULL;
       filed -> toggle2 = NULL;
    } 


    /* Create a tab group for the file dialog. */

    group_count = 0;

    group [group_count++] = filed -> entry;
    group [group_count++] = filed -> viewport;
    if (toggle_labels != NULL) {
       group [group_count++] = filed -> toggle1;
       group [group_count++] = filed -> toggle2;
    }
    group [group_count++] = filed -> okay;
    group [group_count++] = filed -> cancel;

    XtGetValues (filed -> layout, color_args, XtNumber (color_args));
    CreateTabGroup (filed -> shell, group, group_count, highlight, True);
    XtRealizeWidget (filed -> shell);


    /* Add the translations to each widget. */

    AddDeleteWindowProtocol   (filed -> shell, "FileDialogCancel()");
    ListAddCursorTranslations (filed -> viewport);
    ListAddCursorAccelerators (filed -> viewport, filed -> entry);
    AddScrollableTextTranslations (filed -> entry);

    XtOverrideTranslations (filed -> entry,    entry_translations);
    XtOverrideTranslations (filed -> viewport, viewport_translations);
    XtOverrideTranslations (filed -> okay,     okay_translations);
    XtOverrideTranslations (filed -> cancel,   cancel_translations);

    XtSetArg (args [0], XtNtranslations, list_translations);
    XtSetValues (filed -> list, args, 1);

    mask = StructureNotifyMask;
    XtAddEventHandler (filed -> directory, mask, False, ResizeHandler, filed);



    /* Add the necessary callbacks. */

    XtAddCallback (filed -> list, XtNcallback, CopySelected, (XtPointer) filed);
    XtAddCallback (filed -> cancel, XtNcallback, Cancel, (XtPointer) filed);
    XtAddCallback (filed -> okay, XtNcallback, Okay, (XtPointer) filed);
  
    if (toggle_labels != NULL) {
       XtAddCallback (filed -> toggle1, XtNcallback, 
                      CheckToggle, (XtPointer) filed);
       XtAddCallback (filed -> toggle2, XtNcallback, 
                      CheckToggle, (XtPointer) filed);

       XtOverrideTranslations (filed -> toggle1,  toggle_translations);
       XtOverrideTranslations (filed -> toggle2,  toggle_translations);

       XtSetArg (args [0], XtNstate, True);
       XtSetValues (filed -> toggle1, args, 1);
       XtSetArg (args [0], XtNstate, False);
       XtSetValues (filed -> toggle2, args, 1);
    }

    return filed;
}


/************************************************************************
 * Function:      FileDialogSelect                          *
 *                                                    *
 * Description:   Pops up the file dialog with the specified shell title,     *
 *          label, and suggestion and waits until a selection is  *
 *          made or the dialog is canceled; answer will point to  *
 *          the selection or NULL if the dialog was canceled      *
 ************************************************************************/

void FileDialogSelect (filed, title, label, suggestion, answer, toggle)
    FileDialog filed;
    String     title;
    String     label;
    String     suggestion;
    String    *answer;
    String    *toggle;
{
    XEvent       event;
    XtAppContext app_context;


    FileDialogPopup (filed, title, label, suggestion, NULL, NULL);

    filed -> status = Waiting;
    app_context = XtWidgetToApplicationContext (filed -> shell);

    while (filed -> status == Waiting) {
      XtAppNextEvent (app_context, &event);
      XtDispatchEvent (&event);
    }

    FileDialogPopdown (filed);

    if (answer != NULL)
      *answer = filed -> status == Canceled ? NULL : filed -> path;

    if (toggle != NULL && filed -> toggle1 != NULL)
       *toggle = FileDialogToggle (filed);
}

/************************************************************************
 * Function:      FileDialogToggle                          *
 *                                                    *
 * Description:   Returns the name of the currently active toggle button.     *
 ************************************************************************/

String FileDialogToggle (filed)
    FileDialog filed;
{
    Arg     args [1];
    Boolean state;
    String  label;


    XtSetArg (args [0], XtNstate, &state); 
    XtGetValues (filed -> toggle1, args, 1);

    XtSetArg (args [0], XtNlabel, &label);

    if (state) 
       XtGetValues (filed -> toggle1_name, args, 1);
    else 
       XtGetValues (filed -> toggle2_name, args, 1);

    return label;
}

/************************************************************************
 * Function:      FileDialogSetToggles                            *
 *                                                    *
 * Description:   Sets the labels for the toggle buttons of the specified     *
 *          file dialog.                                    *
 ************************************************************************/

void FileDialogSetToggles (filed, label1, label2)
    FileDialog filed;
    String     label1;
    String     label2;
{
    Arg args [1];


    if (filed -> toggle1 != NULL && filed -> toggle2 != NULL) {
      XtSetArg (args [0], XtNlabel, label1);
      XtSetValues (filed -> toggle1_name, args, 1);

      XtSetArg (args [0], XtNlabel, label2);
      XtSetValues (filed -> toggle2_name, args, 1);
    }
}

/************************************************************************
 * Function:      FileDialogPopup                                 *
 *                                                    *
 * Description: Pops up the file dialog with the specified shell title, *
 *          label, and suggestion.  If the suggestion is NULL then      *
 *          the current working directory is used.  If the callback     *
 *          is not NULL then it will be called upon a selection or      *
 *          cancelation with the specified client data.           *
 ************************************************************************/

void FileDialogPopup (filed, title, label, suggestion, callback, client_data)
    FileDialog       filed;
    String     title;
    String     label;
    String     suggestion;
    XtCallbackProc callback;
    XtPointer        client_data;
{
    Arg args [1];


    XtSetArg (args [0], XtNtitle, title);
    XtSetValues (filed -> shell, args, 1);

    XtSetArg (args [0], XtNlabel, label);
    XtSetValues (filed -> label, args, 1);

    if (suggestion == NULL)
      getcwd (filed -> path, MaxPathLen);
    else if (suggestion [0] == '/' || suggestion [0] == '~')
      strcpy (filed -> path, suggestion);
    else {
      getcwd (filed -> path, MaxPathLen);
      strcat (filed -> path, "/");
      strcat (filed -> path, suggestion);
    }

    SetTextString (filed -> entry, filed -> path);

    filed -> callback = callback;
    filed -> client_data = client_data;

    SetFocus (filed -> entry);
    XtCallCallbacks (filed -> okay, XtNcallback, (XtPointer) filed);
    XtPopup (filed -> shell, callback == NULL ? XtGrabExclusive : XtGrabNone);
}


/************************************************************************
 * Function:      FileDialogPopdown                         *
 *                                                    *
 * Descripion:    Pops down the specified file dialog             *
 ************************************************************************/

void FileDialogPopdown (filed)
    FileDialog filed;
{
    XtPopdown (filed -> shell);
}

Generated by  Doxygen 1.6.0   Back to index