aboutsummaryrefslogtreecommitdiff
path: root/SrcUnix/espws-2.0/FileChooser2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'SrcUnix/espws-2.0/FileChooser2.cxx')
-rw-r--r--SrcUnix/espws-2.0/FileChooser2.cxx645
1 files changed, 645 insertions, 0 deletions
diff --git a/SrcUnix/espws-2.0/FileChooser2.cxx b/SrcUnix/espws-2.0/FileChooser2.cxx
new file mode 100644
index 0000000..b77a35c
--- /dev/null
+++ b/SrcUnix/espws-2.0/FileChooser2.cxx
@@ -0,0 +1,645 @@
+//
+// "$Id: FileChooser2.cxx,v 1.22 2000/01/04 13:45:51 mike Exp $"
+//
+// More FileChooser routines.
+//
+// Copyright 1997-2000 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "COPYING" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: ESP Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: info@easysw.com
+// WWW: http://www.easysw.com
+//
+// Contents:
+//
+// FileChooser::directory() - Set the directory in the file chooser.
+// FileChooser::count() - Return the number of selected files.
+// FileChooser::value() - Return a selected filename.
+// FileChooser::up() - Go up one directory.
+// FileChooser::newdir() - Make a new directory.
+// FileChooser::rescan() - Rescan the current directory.
+// FileChooser::fileListCB() - Handle clicks (and double-clicks) in the
+// FileBrowser.
+// FileChooser::fileNameCB() - Handle text entry in the FileBrowser.
+//
+
+//
+// Include necessary headers.
+//
+
+#include "FileChooser.h"
+#include <FL/filename.H>
+#include <FL/fl_ask.H>
+#include <FL/x.H>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#if defined(WIN32) || defined(__EMX__)
+# include <direct.h>
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+//
+// 'FileChooser::directory()' - Set the directory in the file chooser.
+//
+
+void
+FileChooser::directory(const char *d) // I - Directory to change to
+{
+ char pathname[1024], // Full path of directory
+ *pathptr, // Pointer into full path
+ *dirptr; // Pointer into directory
+ int levels; // Number of levels in directory
+
+
+ // NULL == current directory
+ if (d == NULL)
+ d = ".";
+
+ if (d[0] != '\0')
+ {
+ // Make the directory absolute...
+#if defined(WIN32) || defined(__EMX__)
+ if (d[0] != '/' && d[0] != '\\' && d[1] != ':')
+#else
+ if (d[0] != '/' && d[0] != '\\')
+#endif /* WIN32 || __EMX__ */
+ filename_absolute(directory_, d);
+ else
+ {
+ strncpy(directory_, d, sizeof(directory_) - 1);
+ directory_[sizeof(directory_) - 1] = '\0';
+ }
+
+ // Strip any trailing slash and/or period...
+ dirptr = directory_ + strlen(directory_) - 1;
+ if (*dirptr == '.')
+ *dirptr-- = '\0';
+ if ((*dirptr == '/' || *dirptr == '\\') && dirptr > directory_)
+ *dirptr = '\0';
+ }
+ else
+ directory_[0] = '\0';
+
+ // Clear the directory menu and fill it as needed...
+ dirMenu->clear();
+#if defined(WIN32) || defined(__EMX__)
+ dirMenu->add("My Computer");
+#else
+ dirMenu->add("File Systems");
+#endif /* WIN32 || __EMX__ */
+
+ levels = 0;
+ for (dirptr = directory_, pathptr = pathname; *dirptr != '\0';)
+ {
+ if (*dirptr == '/' || *dirptr == '\\')
+ {
+ // Need to quote the slash first, and then add it to the menu...
+ *pathptr++ = '\\';
+ *pathptr++ = '/';
+ *pathptr++ = '\0';
+ dirptr ++;
+
+ dirMenu->add(pathname);
+ levels ++;
+ pathptr = pathname;
+ }
+ else
+ *pathptr++ = *dirptr++;
+ }
+
+ if (pathptr > pathname)
+ {
+ *pathptr = '\0';
+ dirMenu->add(pathname);
+ levels ++;
+ }
+
+ dirMenu->value(levels);
+
+ // Rescan the directory...
+ rescan();
+}
+
+
+//
+// 'FileChooser::count()' - Return the number of selected files.
+//
+
+int // O - Number of selected files
+FileChooser::count()
+{
+ int i; // Looping var
+ int count; // Number of selected files
+ const char *filename; // Filename in input field or list
+ char pathname[1024]; // Full path to file
+
+
+ if (type_ != MULTI)
+ {
+ // Check to see if the file name input field is blank...
+ filename = fileName->value();
+ if (filename == NULL || filename[0] == '\0')
+ return (0);
+
+ // Is the file name a directory?
+ if (directory_[0] != '\0')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ if (filename_isdir(pathname) && !directory_chooser_)
+ return (0);
+ else
+ return (1);
+ }
+
+ for (i = 1, count = 0; i <= fileList->size(); i ++)
+ if (fileList->selected(i))
+ {
+ // See if this file is a directory...
+ filename = (char *)fileList->text(i);
+ if (directory_[0] != '\0')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ if (!filename_isdir(pathname) || directory_chooser_)
+ count ++;
+ }
+
+ return (count);
+}
+
+
+//
+// 'FileChooser::value()' - Return a selected filename.
+//
+
+const char * // O - Filename or NULL
+FileChooser::value(int f) // I - File number
+{
+ int i; // Looping var
+ int count; // Number of selected files
+ const char *name; // Current filename
+ static char pathname[1024]; // Filename + directory
+
+// There seems to be a little bit of a bug...sometimes
+// the returned path can start with '//'. I think the
+// Unix file system handles this OK ("ls //tmp" works),
+// but lets clean it up anyway.
+
+ if (strlen (directory_) >= 2 &&
+ directory_[0] == '/' && directory_[1] == '/')
+ {
+ memmove (directory_, directory_ + 1, strlen (directory_));
+ }
+
+ if (type_ != MULTI)
+ {
+ name = fileName->value();
+ if (name[0] == '\0')
+ return (NULL);
+
+ sprintf(pathname, "%s/%s", directory_, name);
+ return ((const char *)pathname);
+ }
+
+ for (i = 1, count = 0; i <= fileList->size(); i ++)
+ if (fileList->selected(i))
+ {
+ // See if this file is a directory...
+ name = fileList->text(i);
+ sprintf(pathname, "%s/%s", directory_, name);
+
+ if (!filename_isdir(pathname) || directory_chooser_)
+ {
+ // Nope, see if this this is "the one"...
+ count ++;
+ if (count == f)
+ return ((const char *)pathname);
+ }
+ }
+
+ return (NULL);
+}
+
+
+//
+// 'FileChooser::value()' - Set the current filename.
+//
+
+void
+FileChooser::value(const char *filename) // I - Filename + directory
+{
+ int i, // Looping var
+ count; // Number of items in list
+ char *slash; // Directory separator
+ char pathname[1024]; // Local copy of filename
+
+
+ // See if the filename is actually a directory...
+ if (filename == NULL || filename_isdir(filename))
+ {
+ // Yes, just change the current directory...
+ directory(filename);
+ return;
+ }
+
+ // Switch to single-selection mode as needed
+ if (type_ == MULTI)
+ type(SINGLE);
+
+ // See if there is a directory in there...
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+
+ if ((slash = strrchr(pathname, '/')) == NULL)
+ slash = strrchr(pathname, '\\');
+
+ if (slash != NULL)
+ {
+ // Yes, change the display to the directory...
+ *slash++ = '\0';
+ directory(pathname);
+ }
+ else
+ slash = pathname;
+
+ // Set the input field to the remaining portion
+ fileName->value(slash);
+ fileName->position(0, strlen(slash));
+ okButton->activate();
+
+ // Then find the file in the file list and select it...
+ count = fileList->size();
+
+ for (i = 1; i <= count; i ++)
+ if (strcmp(fileList->text(i), slash) == 0)
+ {
+ fileList->select(i);
+ break;
+ }
+}
+
+
+//
+// 'FileChooser::up()' - Go up one directory.
+//
+
+void
+FileChooser::up()
+{
+ char *slash; // Trailing slash
+
+
+ if ((slash = strrchr(directory_, '/')) == NULL)
+ slash = strrchr(directory_, '\\');
+
+ if (directory_[0] != '\0')
+ dirMenu->value(dirMenu->value() - 1);
+
+ if (slash != NULL)
+ *slash = '\0';
+ else
+ {
+ upButton->deactivate();
+ directory_[0] = '\0';
+ }
+
+ rescan();
+}
+
+
+//
+// 'FileChooser::newdir()' - Make a new directory.
+//
+
+void
+FileChooser::newdir()
+{
+ const char *dir; // New directory name
+ char pathname[1024]; // Full path of directory
+
+
+ // Get a directory name from the user
+ if ((dir = fl_input("New Directory?", NULL)) == NULL)
+ return;
+
+ // Make it relative to the current directory as needed...
+#if defined(WIN32) || defined(__EMX__)
+ if (dir[0] != '/' && dir[0] != '\\' && dir[1] != ':')
+#else
+ if (dir[0] != '/' && dir[0] != '\\')
+#endif /* WIN32 || __EMX__ */
+ sprintf(pathname, "%s/%s", directory_, dir);
+ else
+ {
+ strncpy(pathname, dir, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ // Create the directory; ignore EEXIST errors...
+#if defined(WIN32) || defined(__EMX__)
+ if (mkdir(pathname))
+#else
+ if (mkdir(pathname, 0777))
+#endif /* WIN32 || __EMX__ */
+ if (errno != EEXIST)
+ {
+ fl_alert("Unable to create directory!");
+ return;
+ }
+
+ // Show the new directory...
+ directory(pathname);
+}
+
+
+//
+// 'FileChooser::rescan()' - Rescan the current directory.
+//
+
+void
+FileChooser::rescan()
+{
+ // Clear the current filename
+ fileName->value("");
+ okButton->deactivate();
+
+ // Build the file list...
+ fileList->load(directory_);
+}
+
+
+//
+// 'FileChooser::fileListCB()' - Handle clicks (and double-clicks) in the
+// FileBrowser.
+//
+
+void
+FileChooser::fileListCB()
+{
+ char *filename, // New filename
+ pathname[1024]; // Full pathname to file
+
+
+ filename = (char *)fileList->text(fileList->value());
+ if (directory_[0] != '\0')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+
+ if (Fl::event_clicks())
+ {
+#if defined(WIN32) || defined(__EMX__)
+ if ((strlen(pathname) == 2 && pathname[1] == ':') ||
+ filename_isdir(pathname))
+#else
+ if (filename_isdir(pathname))
+#endif /* WIN32 || __EMX__ */
+ {
+ directory(pathname);
+ upButton->activate();
+ }
+ else
+ window->hide();
+ }
+ else
+ {
+ fileName->value(filename);
+
+ if (!filename_isdir(pathname) || directory_chooser_)
+ okButton->activate();
+ }
+}
+
+
+//
+// 'FileChooser::fileNameCB()' - Handle text entry in the FileBrowser.
+//
+
+void
+FileChooser::fileNameCB()
+{
+ char *filename, // New filename
+ *slash, // Pointer to trailing slash
+ pathname[1024]; // Full pathname to file
+ int i, // Looping var
+ min_match, // Minimum number of matching chars
+ max_match, // Maximum number of matching chars
+ num_files, // Number of files in directory
+ first_line; // First matching line
+ const char *file; // File from directory
+
+
+ // Get the filename from the text field...
+ filename = (char *)fileName->value();
+
+ if (filename == NULL || filename[0] == '\0')
+ {
+ okButton->deactivate();
+ return;
+ }
+
+#if defined(WIN32) || defined(__EMX__)
+ if (directory_[0] != '\0' &&
+ filename[0] != '/' &&
+ filename[0] != '\\' &&
+ !(isalpha(filename[0]) && filename[1] == ':'))
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+#else
+ if (directory_[0] != '\0' &&
+ filename[0] != '/')
+ sprintf(pathname, "%s/%s", directory_, filename);
+ else
+ {
+ strncpy(pathname, filename, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ }
+#endif /* WIN32 || __EMX__ */
+
+ if (Fl::event_key() == FL_Enter)
+ {
+ // Enter pressed - select or change directory...
+
+#if defined(WIN32) || defined(__EMX__)
+ if (((strlen(pathname) == 2 && pathname[1] == ':') ||
+ filename_isdir(pathname)) && !directory_chooser_)
+#else
+ if (filename_isdir(pathname) && !directory_chooser_)
+#endif /* WIN32 || __EMX__ */
+ directory(pathname);
+ else if (type_ == CREATE || access(pathname, 0) == 0)
+ {
+ // New file or file exists... If we are in multiple selection mode,
+ // switch to single selection mode...
+ if (type_ == MULTI)
+ type(SINGLE);
+
+ // Hide the window to signal things are done...
+ window->hide();
+ }
+ else
+ {
+ // File doesn't exist, so beep at and alert the user...
+ // TODO: NEED TO ADD fl_beep() FUNCTION TO 2.0!
+#ifdef WIN32
+ MessageBeep(MB_ICONEXCLAMATION);
+#else
+ XBell(fl_display, 100);
+#endif // WIN32
+
+ fl_alert("Please choose an existing file!");
+ }
+ }
+ else if (Fl::event_key() != FL_Delete)
+ {
+ // Check to see if the user has entered a directory...
+ if ((slash = strrchr(filename, '/')) == NULL)
+ slash = strrchr(filename, '\\');
+
+ if (slash != NULL)
+ {
+ // Yes, change directories and update the file name field...
+ if ((slash = strrchr(pathname, '/')) == NULL)
+ slash = strrchr(pathname, '\\');
+
+ if (slash > pathname) // Special case for "/"
+ *slash++ = '\0';
+ else
+ slash++;
+
+ if (strcmp(filename, "../") == 0) // Special case for "../"
+ up();
+ else
+ directory(pathname);
+
+ // If the string ended after the slash, we're done for now...
+ if (*slash == '\0')
+ return;
+
+ // Otherwise copy the remainder and proceed...
+ fileName->value(slash);
+ fileName->position(strlen(slash));
+ filename = slash;
+ }
+
+ // Other key pressed - do filename completion as possible...
+ num_files = fileList->size();
+ min_match = strlen(filename);
+ max_match = 100000;
+ first_line = 0;
+
+ for (i = 1; i <= num_files && max_match > min_match; i ++)
+ {
+ file = fileList->text(i);
+
+#if defined(WIN32) || defined(__EMX__)
+ if (strnicmp(filename, file, min_match) == 0)
+#else
+ if (strncmp(filename, file, min_match) == 0)
+#endif // WIN32 || __EMX__
+ {
+ // OK, this one matches; check against the previous match
+ if (max_match == 100000)
+ {
+ // First match; copy stuff over...
+ strncpy(pathname, file, sizeof(pathname) - 1);
+ pathname[sizeof(pathname) - 1] = '\0';
+ max_match = strlen(pathname);
+
+ // And then make sure that the item is visible
+ fileList->topline(i);
+ first_line = i;
+ }
+ else
+ {
+ // Succeeding match; compare to find maximum string match...
+ while (max_match > min_match)
+#if defined(WIN32) || defined(__EMX__)
+ if (strnicmp(file, pathname, max_match) == 0)
+#else
+ if (strncmp(file, pathname, max_match) == 0)
+#endif // WIN32 || __EMX__
+ break;
+ else
+ max_match --;
+
+ // Truncate the string as needed...
+ pathname[max_match] = '\0';
+ }
+ }
+ }
+
+ fileList->deselect(0);
+ fileList->redraw();
+
+ // If we have any matches, add them to the input field...
+ if (first_line > 0 && min_match == max_match &&
+ max_match == (int)strlen(fileList->text(first_line)))
+ fileList->select(first_line);
+ else if (max_match > min_match && max_match != 100000)
+ {
+ // Add the matching portion...
+ fileName->replace(0, min_match, pathname);
+
+ // Highlight it; if the user just pressed the backspace
+ // key, position the cursor at the start of the selection.
+ // Otherwise, put the cursor at the end of the selection so
+ // s/he can press the right arrow to accept the selection
+ // (Tab and End also do this for both cases.)
+ if (Fl::event_key() == FL_BackSpace)
+ fileName->position(min_match - 1, max_match);
+ else
+ fileName->position(max_match, min_match);
+ }
+
+ // See if we need to enable the OK button...
+ sprintf(pathname, "%s/%s", directory_, fileName->value());
+
+ if ((type_ == CREATE || access(pathname, 0) == 0) &&
+ (!filename_isdir(pathname) || directory_chooser_))
+ okButton->activate();
+ else
+ okButton->deactivate();
+ }
+}
+
+
+//
+// End of "$Id: FileChooser2.cxx,v 1.22 2000/01/04 13:45:51 mike Exp $".
+//