file: fileio.c

/********************************************************************** * filemenu.c * * See SelFile() header for interface description. * * Copyright 1990, David Nedde * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is granted * provided that the above copyright notice appears in all copies. * It is provided "as is" without express or implied warranty. * * This source is derived from xdbx source with the following disclaimer: **********************************************************************/ /***************************************************************************** * * xdbx - X Window System interface to the dbx debugger * * Copyright 1989 The University of Texas at Austin * Copyright 1990 Microelectronics and Computer Technology Corporation * * 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 The University of Texas * and Microelectronics and Computer Technology Corporation (MCC) not be * used in advertising or publicity pertaining to distribution of * the software without specific, written prior permission. The * University of Texas and MCC makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC 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: Po Cheung * Created: March 10, 1989 * *****************************************************************************/ /* filemenu.c * * Construct a file menu (directory browser) which allows a user to go * up and down the directory tree, to select files. * The file menu is popped up by the 'file' command button. * Duane Voth (duanev@mcc.com) contributed to the layout of the file menu, * plus some code and ideas. * * changeDir(): Record the current working directory. * InList(): Select files to be displayed in the menu. * ScanDir(): Scan the directory and record selected filenames. * DisplayMenuFile(): Callback for the file menu. * CancelFileMenu(): Pop down the file menu. * SetUpFileMenu(): Create the file menu popupshell. * UpdateFileMenu(): Update entries in the file menu. * File(): Command callback for the 'file' command button. */ #include <sys/param.h> #include <sys/stat.h> #include <ctype.h> #include <X11/Xos.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Shell.h> #include <X11/Xaw/Command.h> #include <X11/Xaw/Dialog.h> #include <X11/Xaw/Label.h> #include <X11/Xaw/List.h> #include <X11/Xaw/Paned.h> #include "XmdvTool.h" #include "brush.h" #include "init.h" #include "util.h" #include "fileio.h" static int glob_status; static char **glob_path; static Widget parent_w; char cwd[MAXPATHLEN]; /* current working directory */ static char fileMenuDir[MAXPATHLEN];/* current directory of file menu */ static char **filelist; /* list of file names in fileMenu */ static int nfiles = 0; /* number of files in filelist */ static Widget popupshell, /* parent of popup */ popup, /* vpane widget containing file menu */ fileMenu, /* list widget as file menu */ fileMenuLabel; /* label widget as file menu label */ Arg wargs[10]; int n; extern Widget appShell; extern int dims; /* Change working directory to 'dir'. * Modify static global variable, cwd, to keep track of * current working directory. */ static void changeDir(char *dir) { int i; if (strcmp(dir, "./") == 0) return; if (dir[0] == '/' || dir[0] == '~') strcpy(cwd, dir); if (strcmp(dir, "../") == 0) { for (i=strlen(cwd); cwd[i] != '/' && i > 0; i--); cwd[i] = '\0'; if (strcmp(cwd, "") == 0) strcpy(cwd, "/"); } else { sprintf(cwd, "%s/%s", cwd, dir); LASTCH(cwd) = '\0'; } } /* Determines if a directory entry should appear in the file menu. * The files included in the menu are : * .. (parent directory) * directories * text files * executable files */ static int InList(Directory *entry) //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?) { char pathname[LINESIZ]; struct stat statbuf; if (strcmp(entry->d_name, ".") == 0 || /* ignore current directory */ LASTCH(entry->d_name) == '~' || /* ignore Emacs backup files */ entry->d_name[0] == '#' || /* Ignore emacs backup files */ (LASTCH(entry->d_name) == 'o' && SECLASTCH(entry->d_name) == '.')) /* ignore object files */ return False; if (entry->d_name[0] == '.' && entry->d_name[1] != '.') return False; /* ignore hidden files */ if (strcmp(cwd, "")) /* give full path name */ sprintf(pathname, "%s/%s", cwd, entry->d_name); else strcpy(pathname, entry->d_name); if (stat(pathname, &statbuf) == -1) return False; if (statbuf.st_mode & S_IFDIR) { /* is directory */ strcat(entry->d_name, "/"); /* had to put this in since Solaris doesn't have this field defined - Matt */ #ifndef SVR4 ++(entry->d_namlen); #endif return True; } if (statbuf.st_mode & S_IEXEC) { /* is executable */ strcat(entry->d_name, "*"); #ifndef SVR4 ++(entry->d_namlen); #endif return True; } return True; } /* Scans the working directory for files selected by InList(), sorted * alphabetically, and stored in an array of pointers to directory * entries called namelist. * The names of the selected files are stored in filelist. */ static int ScanDir(char *dir) { Directory **namelist; //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?) int i, j; char *format_static(); /* for BSD systems, just use scandir to read in directory */ #ifndef SVR4 extern alphasort(); nfiles = scandir(dir, &namelist, InList, alphasort); #else /* for Solaris, use opendir, readdir, malloc, qsort, and closedir instead */ DIR *dirp; Directory *item; //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?) int asort(const void *, const void *); dirp = opendir(dir); if(dirp == NULL) return(-1); /* count how many entries in directory, and make sufficient space */ i = 0; while((item = readdir(dirp)) != NULL) i++; rewinddir(dirp); namelist = (Directory **)malloc(i * sizeof(Directory *)); //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?); Directory: fileio.h(?), fileio.h(?) /* get each directory entry, filter non-data files, and copy info - only really need d_name - may be able to eliminate others, since they are not POSIX standard */ i = 0; while((item = readdir(dirp)) != NULL) { if(InList(item)) { namelist[i] = (Directory *)malloc(sizeof(Directory) + //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?); Directory: fileio.h(?), fileio.h(?) ((strlen(item->d_name) + 4) & ~3)); namelist[i]->d_ino = item->d_ino; namelist[i]->d_off = item->d_off; namelist[i]->d_reclen = item->d_reclen; strcpy(namelist[i]->d_name, item->d_name); i++; } } /* sort the names alphabetically */ nfiles = i; qsort(namelist, nfiles, sizeof(Directory *), asort); //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?) closedir(dirp); #endif if (nfiles <= 0) { XBell(XtDisplay(popupshell),0); return(INVALID); } if (filelist) { for (i=0; filelist[i]; i++) XtFree(filelist[i]); XtFree((void *)filelist); } filelist = (char **) XtMalloc((nfiles+1) * sizeof(char *)); i = 0; for (j=0; j<nfiles; j++) { filelist[i++] = XtNewString(namelist[j]->d_name); XtFree((void *)namelist[j]); } filelist[i++] = NULL; XtFree((void *)namelist); return(OK); } int asort(const void *d1, const void *d2) { return(strcmp((*(Directory **)d1)->d_name, (*(Directory **)d2)->d_name)); //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?); Directory: fileio.h(?), fileio.h(?) } /* Delete the current directory prefix from the passed path */ char *remove_current_prefix(char *path) { char wd[MAXPATHLEN]; char *temp_str; getwd(wd); if (!strncmp(wd,path,strlen(wd))) { /* wd matches path prefix */ temp_str = &path[strlen(wd)]; if (temp_str[0] == '/') /* If first char of prefix is a '/', * * remove it since we want a relative path */ temp_str++; return(temp_str); } /* Couldn't find the prefix -- return the whole path */ return(path); } /* Callback for the fileMenu list widget. * > if the selected item is a directory, display contents of that directory. * > if the selected item is a readable file, return the file name */ /* ARGSUSED */ static void DisplayMenuFile(Widget w, Widget popupshell, XawListReturnStruct *call_data) { char *filename; XtPopdown(popupshell); filename = call_data->string; if (filename == NULL) return; if (LASTCH(filename) == '/') { changeDir(filename); XtDestroyWidget(popupshell); if (UpdateFileMenu() == INVALID) changeDir("../"); /* create new menu */ File(w,(caddr_t)0,(caddr_t)0); /* pop it up */ } else { *glob_path = XtMalloc(strlen(filename)+strlen(cwd)+2); strcpy(*glob_path, remove_current_prefix(cwd)); if (strlen(*glob_path) != 0) strcat(*glob_path, "/"); strcat(*glob_path, filename); glob_status = OK; } } /* Callback to popdown the file menu */ /* ARGSUSED */ static void CancelFileMenu(Widget w, Widget popupshell, caddr_t call_data) { XtPopdown(popupshell); glob_status = CANCELED; } void DisableWindowResize(Widget w) { Arg args[MAXARGS]; Cardinal n; Dimension height; n = 0; XtSetArg(args[n], XtNheight, &height); n++; XtGetValues(w, args, n); XawPanedSetMinMax(w, height, height); XawPanedAllowResize(w, False); } /* Creates a popup shell with its child being a vpane widget containing * a file menu label, a file menu containing file names returned from * ScanDir(), and a cancel command button. * When an item in the list is selected, DisplayMenuFile is called. */ static int SetUpFileMenu(char *dir) { Widget cancelButton; Arg args[MAXARGS]; Cardinal n; char menulabel[LINESIZ]; int ncolumns; n = 0; popupshell = XtCreatePopupShell("File Directory", transientShellWidgetClass, //OVERLOAD CALL: Directory: fileio.h(?), fileio.h(?) parent_w, args, n); n = 0; popup = XtCreateManagedWidget("popup", panedWidgetClass, popupshell, args, n); if (ScanDir(dir) == OK) /* It worked OK */ strcpy(fileMenuDir, dir); else return(INVALID); n = 0; sprintf(menulabel, " %s ", dir); XtSetArg(args[n], XtNlabel, (XtArgVal) menulabel); n++; XtSetArg(args[n], XtNjustify, (XtArgVal) XtJustifyCenter); n++; fileMenuLabel = XtCreateManagedWidget("fileMenuLabel", labelWidgetClass, popup, args, n); n = 0; ncolumns = nfiles/FILES_PER_COL + 1; ncolumns = MIN(ncolumns, MAXCOLUMNS); XtSetArg(args[n], XtNlist, filelist); n++; XtSetArg(args[n], XtNverticalList, True); n++; XtSetArg(args[n], XtNdefaultColumns, (XtArgVal) ncolumns); n++; fileMenu = XtCreateManagedWidget("fileMenu", listWidgetClass, popup, args, n); XtAddCallback(fileMenu, XtNcallback, DisplayMenuFile, popupshell); n = 0; XtSetArg(args[n], XtNresize, False); n++; XtSetArg(args[n], XtNlabel, "CANCEL"); n++; cancelButton = XtCreateManagedWidget("cancelButton", commandWidgetClass, popup, args, n); XtAddCallback(cancelButton, XtNcallback, CancelFileMenu, popupshell); DisableWindowResize(fileMenuLabel); DisableWindowResize(cancelButton); return(OK); } /* This routine is called when there is a a change in current directory. * It destroys the existing popup shell and creates a new file menu based * on the new current directory. A new directory list is created. */ static int UpdateFileMenu(void) { return(SetUpFileMenu(cwd)); } /* File command button callback. */ /* ARGSUSED */ void File(Widget w, caddr_t client_data, caddr_t call_data) { Arg args[MAXARGS]; Cardinal n; Dimension fileMenu_width, fileMenuLabel_width, border_width; /* if (strcmp(fileMenuDir, cwd))*/ if (UpdateFileMenu() != OK) return; n = 0; XtSetArg(args[n], XtNwidth, &fileMenu_width); n++; XtSetArg(args[n], XtNborderWidth, &border_width); n++; XtGetValues(fileMenu, args, n); n = 0; XtSetArg(args[n], XtNwidth, &fileMenuLabel_width); n++; XtGetValues(fileMenuLabel, args, n); #if 0 /* In case we want to place the popup window... */ n = 0; XtSetArg(args[n], XtNwidth, &dialog_width); n++; XtGetValues(dialogWindow, args, n); width = MAX(fileMenu_width, fileMenuLabel_width); x_offset = (Position) (dialog_width - width - border_width); XtTranslateCoords(dialogWindow, x_offset, 0, &x, &y); x = MAX(0, x); y = MAX(0, y); n = 0; XtSetArg(args[n], XtNx, x); n++; XtSetArg(args[n], XtNy, y); n++; XtSetValues(popupshell, args, n); #else PlaceWindow(popupshell,"*viewport,-1,-1",(char *)0); #endif XtPopup(popupshell, XtGrabNonexclusive); /*UpdateMessageWindow("Select a file or directory");*/ } /********************************************************************** * SelFile * * Pop up a window, letting the user select a file. When the file * is selected, the string is returned to the caller. * * If the init_path is NULL and this is the first call, the current * directory is used, else the previous call's directory is used. * If the init_path is an empty string, the current directory is used. * A passed init path will have the current dir prepended if the path * doesn't start with a '/'. * If the popup is canceled, -1 is returned, otherwise 0 is returned. **********************************************************************/ int SelFile(Widget w, char *init_path, char **path_return) { XEvent event; parent_w = w; glob_path = path_return; if (init_path == (char *)0 || init_path[0] == '\0') { /* No init_path -- Use the current working directory */ if (cwd[0] == '\0' || init_path[0] == '\0') getwd(cwd); } else if (strcmp(cwd,init_path)) { /* They are different -- copy requested starting dir in */ /* Prefix with wd if init_path is a relative path */ if (init_path[0] != '/') { getwd(cwd); strcat(cwd,"/"); } else cwd[0] = '\0'; strcat(cwd,init_path); } glob_status = INVALID; File(w, (caddr_t)0, (caddr_t)0); while (glob_status == INVALID) { XtNextEvent(&event); XtDispatchEvent(&event); } return(glob_status); } extern int sbt_open; /********************************************************************** * LoadFile * * Resource file syntax: * LoadFile() * * Popup a load file widget and load the selected file * **********************************************************************/ void LoadFile(Widget w, caddr_t call_data) { int ret; /* The return value from the selfile popup */ char *path; /* Path returned from selfile */ char *old_path; /* The current path loaded into the sequence */ Widget label_w; /* filename label widget */ char *last_slash; /* Used to extract the directory from a path */ /* Widget shell_w; /* the stack brush tool shell widget */ Widget tw; /* data form widget */ /* Get the current filename's value */ if(!(label_w = (Widget)WcFullNameToWidget(w, "*file_name"))) { fprintf(stderr, "Error finding *file_name\n"); exit(-1); } n = 0; XtSetArg(wargs[n],XtNlabel,&old_path); n++; XtGetValues(label_w,wargs,n); /* Remove the trailing filename leaving only the path */ last_slash = strrchr(old_path,'/'); if (last_slash == NULL) /* No directories involved -- start from current directory */ old_path[0] = '\0'; else /* There was a directory -- Start from the currently loaded directory */ *last_slash = '\0'; /* Popup a window letting the user select a file */ ret = SelFile(w, old_path, /* Init_path */ &path); if (ret == -1) return; /* Cancel button pressed */ /* if (!file_openable(path,"r")) { popup_error(form_w, format_static("Opening file '%s': Not a readable file", path)); XtFree(path); return; } */ /* Read in the selected file */ get_head(path); InitBrush(); init_glyphkey(); init_hierkey(); init_DimList(); tw = WcFullNameToWidget(appShell,"*data_form"); /* if(tw == NULL) printf("couldn't get data form widget\n"); else { XawFormDoLayout(tw, True); n = 0; XtSetArg(wargs[n],XtNheight,dims*15); n++; XtSetValues(tw,wargs,n); } */ /* redraw the canvas */ RedrawCanvas(w, NULL, NULL); XtFree(path); }


Back to Source File Index


C++ to HTML Conversion by ctoohtml