This is Dir.c in view mode; [Download] [Up]
/*
* Dir.c - Dir composite widget
*
*/
#if ( !defined(lint) && !defined(SABER))
static char PCN_rcsid[] = "$Header: /ufs/comp/mei/PROJ_PCN/onprofile/IFModel/Xsw/RCS/Dir.c,v 1.1 1992/04/17 18:23:47 mei Exp $";
#endif
/******************************************************************************
* *
* Copyright (C) The Aerospace Corporation 1991 *
* *
* This software was developed by The Aerospace Corporation as a *
* research endeavor for the United States Air Force *
* Space Systems Division. The current version of the Gauge *
* computer program is available for release to you for *
* educational and research purposes only. It is not *
* to be used for commercial purposes. *
* *
* In addition, the following conditions shall apply. *
* *
* 1) The computer software and documentation were designed to *
* satisfy internal Aerospace requirements only. *
* The software is provided ``as is,'' and The Aerospace Corporation *
* makes no warranty, expressed or implied, as to it accuracy, *
* functioning, or fitness for a particular purpose. *
* *
* 2) The Aerospace Corporation and its personnel are not *
* responsible for providing technical support or general assistance *
* with respect to the software. *
* *
* 3) Neither The Aerospace Corporation nor its personnel shall be *
* liable for claims, losses, or damages arising out of or connected *
* with the use of this software. *
* Your sole and exclusive remedy shall be to request a replacement *
* copy of the program. *
* *
******************************************************************************/
#include <sys/types.h>
/* Steve Tuecke, 11/9/92 -- changed to use dirent instead of direct */
#ifdef next040
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
/*
#include <sys/dir.h>
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <X11/IntrinsicP.h>
#include <X11/Xresource.h>
#include "Xsw.h"
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Label.h>
#include "MultiList.h"
#include "FileObjects.h"
#include "DirP.h"
#define NENTRIES 20
#define TWIDDLE '~' /* Emacs backup file suffix. */
#define EOS 0
extern int sys_nerr;
extern char* sys_errlist[];
/****************************************************************
*
* dir Resources
*
****************************************************************/
static XtResource resources[] = {
#define offset(field) XtOffset(DirWidget, dir.field)
{ XtNdirectoryChange, XtCDirectoryChange, XtRCallback,
sizeof(XtPointer), offset(directory_change), XtRImmediate,
(XtPointer)NULL },
{ XtNuserDirectory, XtCUserDirectory, XtRCallback,
sizeof(XtPointer), offset(user_directory), XtRImmediate,
(XtPointer)NULL },
{ XtNcurrentDirectory, XtCCurrentDirectory, XtRString, sizeof(String),
offset(current_dir), XtRString, NULL},
{ XtNextensions, XtCExtensions, XtRSCPairList, sizeof(SCPairList),
offset(extensions), XtRString, ""},
{ XtNfullPath, XtCFullPath, XtRBoolean, sizeof(Boolean),
offset(full_path), XtRString, "False"},
{ XtNinterval, XtCInterval, XtRInt, sizeof(int),
offset(interval), XtRString, "10"},
{ XtNselectType, XtCSelectType, XtRSType, sizeof(SType),
offset(select_type), XtRString, "Single"},
{ XtNshowDirectories, XtCShowDirectories, XtRBoolean, sizeof(Boolean),
offset(show_directories), XtRString, "True"},
{ XtNshowDotFiles, XtCShowDotFiles, XtRBoolean, sizeof(Boolean),
offset(show_dot_files), XtRString, "False"},
{ XtNshowBackupFiles, XtCShowBackupFiles, XtRBoolean, sizeof(Boolean),
offset(show_backup_files), XtRString, "False"},
};
/****************************************************************
*
* Full class record constant
*
****************************************************************/
static void Initialize();
static void Destroy();
static void ClassPartInitialize();
static StringList MakeFileList();
DirClassRec dirClassRec = {
{
/* core_class fields */
/* superclass */ (WidgetClass) &formClassRec,
/* class_name */ "dir",
/* widget_size */ sizeof(DirRec),
/* class_initialize */ NULL,
/* class_part_init */ ClassPartInitialize,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ NULL,
/* num_actions */ 0,
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave*/ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* resize */ XtInheritResize,
/* expose */ NULL,
/* set_values */ NULL,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ NULL,
/* dir_geometry */ XtInheritQueryGeometry,
/* display_accelerator*/ XtInheritDisplayAccelerator,
/* extension */ NULL
},{
/* composite_class fields */
/* geometry_manager */ XtInheritGeometryManager,
/* change_managed */ XtInheritChangeManaged,
/* insert_child */ XtInheritInsertChild,
/* delete_child */ XtInheritDeleteChild,
/* extension */ NULL
},{
/* constraint class fields */
/* subresources */ NULL,
/* subresource_count */ 0,
/* constraint_size */ sizeof(DirConstraintsRec),
/* initialize */ NULL,
/* destroy */ NULL,
/* set_values */ NULL,
/* extension */ NULL
},{
/* form_class fields */
/* layout */ XtInheritLayout }
};
WidgetClass dirWidgetClass = (WidgetClass)&dirClassRec;
#define IsFileExt(file,ext) (!strcmp(file+strlen(file)- strlen(ext),ext))
static void
BackgroundDirectoryUpdate(w, id)
DirWidget w;
XtIntervalId *id;
{
struct stat stat_struct;
int ret;
ret = stat(w->dir.current_dir, &stat_struct);
if(ret != 0 && ! w->dir.pending_error) {
w->dir.pending_error = True;
XtWarning((ret < sys_nerr) ? sys_errlist[ret] : "Stat failed");
}
if (w->dir.mod_time != stat_struct.st_mtime)
{
XswDirUpdate(w);
}
w->dir.timer_proc_id =
XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w),
(unsigned long)(w->dir.interval*100),
BackgroundDirectoryUpdate, w);
}
static String
FullName(dir, name)
char *dir;
char *name;
{
static char fullpath[MAXPATHLEN];
if (!strcmp(name, "..")) {
char *cPtr;
strcpy(fullpath, dir);
cPtr = strrchr(fullpath, '/');
if (cPtr == NULL) strcpy(fullpath, "/");
/* hui 4/16 change assignment from NULL */
else *cPtr ='\0';
} else {
sprintf(fullpath, "%s/%s", dir, name);
}
return fullpath;
}
static Boolean
CheckMode(name, mode)
char *name;
u_short mode;
{
struct stat statbuf;
if (stat(name, &statbuf)) {
return False;
}
if (statbuf.st_mode & mode)
return True;
else
return False;
}
static Boolean
IsReadable(name)
char *name;
{
FILE *file;
if ((file = fopen(name, "r")) != NULL) {
fclose(file);
return True;
} else {
return False;
}
}
static Boolean
IsAccess(name)
char *name;
{
return (IsReadable(name) && !CheckMode(name, (S_IFSOCK & S_IFIFO)));
}
/* Function: IsDirectory() tests to see if a pathname is a directory.
* Arguments: path: Pathname of file to test.
* Returns: True or False.
* Notes: False is returned if the directory is not accessible.
*/
static Boolean
IsDirectory(path)
char *path;
{
return (CheckMode(path, S_IFDIR));
}
/* Function: DoChangeDir() actually changes the directory and displays
* the new listing.
* Arguments: dir: Pathname of new directory.
* Returns: Nothing.
* Notes:
*NULL for dir means to rebuild the file list for the current directory
* (as in an update to the directory or change in filename filter).
*/
static void
DoChangeDir(w, dir)
DirWidget w;
char * dir;
{
char *p;
Arg args[10];
Cardinal arg_cnt;
String newdir;
struct stat stat_struct;
int ret;
UserDirStruct user_dir_struct;
if (dir != NULL) {
/* dir[strlen(dir)-1] = NULL; */
dir[strlen(dir)-1] = '\0';
newdir = FullName(w->dir.current_dir, dir);
XtFree(w->dir.current_dir);
w->dir.current_dir = XtNewString(newdir);
XtCallCallbacks((Widget) w, XtNdirectoryChange, w->dir.current_dir);
}
if ( w->dir.user_directory ) {
user_dir_struct.dir_name = &(w->dir.current_dir);
user_dir_struct.file_list = &(w->dir.file_list);
XtCallCallbacks((Widget) w, XtNuserDirectory, &(user_dir_struct) );
} else {
ret = stat(w->dir.current_dir, &stat_struct);
if(ret != 0 && ! w->dir.pending_error) {
w->dir.pending_error = True;
XtWarning((ret < sys_nerr) ? sys_errlist[ret] : "Stat failed");
return;
}
w->dir.file_list = MakeFileList(w);
w->dir.mod_time = stat_struct.st_mtime;
}
if (w->dir.file_list == NULL && ! w->dir.pending_error) {
w->dir.pending_error = True;
XtWarning("Unable to list directory");
return;
}
arg_cnt = 0;
XtSetArg(args[arg_cnt], XtNlabel, w->dir.current_dir); arg_cnt++;
XtSetValues(w->dir.label_w, args, arg_cnt);
(void)XswDirGetEntriesAndClear(w);
XswMultiListChange(w->dir.list_w, w->dir.file_list, 0, 0, True);
XtFree(w->dir.cur_selection);
w->dir.cur_selection = XtNewString("");
w->dir.pending_error = False;
}
/*ARGSUSED*/
static void
FileSelected(w, cw, ret_val)
Widget w;
DirWidget cw;
XPointer ret_val;
{
XswMultiListReturnStruct *ret_struct;
char * file_name;
ret_struct =
XswMultiListShowCurrent(w);
if (cw->dir.full_path) {
file_name = FullName(cw->dir.current_dir, ret_struct->string);
} else {
file_name = ret_struct->string;
}
if ((ret_struct->list_index != XSW_LIST_NONE) &&
(cw->dir.cur_selection[0] != 0) &&
!strcmp(cw->dir.cur_selection, file_name)) {
if (IsDirectory(FullName(cw->dir.current_dir,
ret_struct->string))) {
DoChangeDir(cw, ret_struct->string);
} else {
XswSCPairListCall(cw->dir.extensions,
XswGetExtension(cw->dir.extensions, cw->dir.cur_selection),
cw, cw->dir.cur_selection);
XswMultiListUnhighlight(w, ret_struct->list_index);
XtFree(cw->dir.cur_selection);
cw->dir.cur_selection = XtNewString("");
}
} else {
if (cw->dir.select_type != Multi) {
XtFree(cw->dir.cur_selection);
cw->dir.cur_selection = XtNewString(file_name);
} else {
if (IsDirectory(FullName(cw->dir.current_dir,
ret_struct->string))) {
DoChangeDir(cw, ret_struct->string);
}
}
}
XtFree((char *) ret_struct);
}
/* Function: SPComp() compares two string pointers for qsort().
* Arguments: s1, s2: strings to be compared.
* Returns: Value of strcmp().
* Notes:
*/
static int
SPComp(s1, s2)
char **s1, **s2;
{
return(strcmp(*s1, *s2));
}
static Boolean
NoExt(file)
String file;
{
int i;
i = 0;
while ((file[i] != 0) && (file[i] != '.')) i++;
return (file[i] == 0);
}
static int valid_extension(filename,extensions)
char *filename;
char *extensions[];
{
int i = 0;
if (extensions[0] == NULL) return True;
while (extensions[i] != NULL)
if (XswStrCmp(extensions[i], XtNNO_EXTENSION)) {
if (NoExt(filename))
return True;
else
i++;
} else {
if (IsFileExt(filename,extensions[i]))
return(True);
else
i++;
}
return(False);
}
static StringList
MakeFileList(w)
DirWidget w;
{
DIR *dirp;
/* Steve Tuecke, 11/9/92 -- changed to use dirent instead of direct */
#ifdef next040
struct direct *dp;
#else
struct dirent *dp;
#endif
char **filelist;
char **cur_file;
char **last_file;
int entry_cnt;
entry_cnt = NENTRIES;
filelist = (char **) XtCalloc(entry_cnt, sizeof (char *));
cur_file = filelist;
last_file = filelist + entry_cnt - 1;
dirp = opendir(w->dir.current_dir);
if (dirp == NULL) {
return(NULL);
}
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if ( !strcmp(dp->d_name, ".") )
continue;
if ( (!w->dir.show_dot_files) && (dp->d_name[0] == '.') &&
strcmp(dp->d_name, ".."))
continue;
if (!((w->dir.show_directories) &&
IsDirectory(FullName(w->dir.current_dir, dp->d_name)))) {
if (!valid_extension(dp->d_name,w->dir.legal_extensions))
continue;
if ( (!w->dir.show_backup_files) &&
(dp->d_name[strlen(dp->d_name)-1] == TWIDDLE))
continue;
}
if (!IsAccess(FullName(w->dir.current_dir,dp->d_name))) continue;
if (IsDirectory(FullName(w->dir.current_dir, dp->d_name))) {
*cur_file = XtMalloc(sizeof(char)*(strlen(dp->d_name)+3));
sprintf(*cur_file, "%s%s", dp->d_name, "/");
cur_file++;
} else {
*cur_file++ = XtNewString(dp->d_name);
}
if (cur_file == last_file) {
filelist = (char **) XtRealloc((char *) filelist,
2 * entry_cnt * sizeof (char *));
cur_file = filelist + entry_cnt - 1;
entry_cnt = 2 * entry_cnt;
last_file = filelist + entry_cnt - 1;
}
}
*cur_file = NULL;
qsort(filelist, cur_file - filelist, sizeof (char *), SPComp);
return(filelist);
}
/* ARGSUSED */
Boolean CvtStringToSType(display, args, nargs,
fromVal, toVal, converter_data)
Display* display;
XrmValuePtr args, fromVal, toVal;
int *nargs;
XtPointer* converter_data;
{
static int result;
if (XswStrCmp((char *)fromVal->addr, "single"))
result = Single;
else if ((XswStrCmp((char *)fromVal->addr, "multi")) ||
(XswStrCmp((char *)fromVal->addr, "multiple")))
result = Multi;
else
XtStringConversionWarning((char *) fromVal->addr, "SType");
DONE(SType, result);
}
/* ARGSUSED */
static void
ClassPartInitialize(class)
WidgetClass class;
{
XtSetTypeConverter(XtRString, XtRSType,
CvtStringToSType, NULL, 0,
XtCacheAll, NULL);
}
static void
Destroy(w)
DirWidget w;
{
XswFreeStringList(w->dir.return_list);
XswFreeStringList(w->dir.file_list);
XtRemoveTimeOut(w->dir.timer_proc_id);
}
/* ARGSUSED */
static void
Initialize(request, new)
DirWidget request, new;
{
Widget previous_w, vert_w;
Cardinal arg_cnt;
Dimension width;
String dir;
Arg args[20];
int i;
new->dir.return_list = NULL;
new->dir.file_list = NULL;
new->dir.pending_error = False;
new->dir.label_w =
XtVaCreateManagedWidget("dirLabel", labelWidgetClass, (Widget)new,
XtNtop, XtChainTop,
XtNbottom, XtChainTop,
XtNright, XtChainRight,
XtNleft, XtChainLeft, NULL);
new->dir.viewer_w =
XtVaCreateManagedWidget("dirVport", viewportWidgetClass, (Widget)new,
XtNallowVert, True,
XtNfromVert, new->dir.label_w,
XtNtop, XtChainTop,
XtNbottom, XtChainBottom,
XtNright, XtChainRight,
XtNleft, XtChainLeft, NULL);
new->dir.legal_extensions =
XswSCPairListGetStrings(new->dir.extensions);
new->dir.cur_selection = XtNewString("");
new->dir.list_w =
XtVaCreateManagedWidget("dirList", multiListWidgetClass,
new->dir.viewer_w,
XtNsingle, (new->dir.select_type == Single),
NULL);
XtAddCallback(new->dir.list_w, XtNcallback, FileSelected, new);
if ( new->dir.interval )
new->dir.timer_proc_id =
XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) new),
(unsigned long)(new->dir.interval*100),
BackgroundDirectoryUpdate, new);
if (new->dir.current_dir == NULL) {
new->dir.current_dir = XtMalloc(sizeof(char)*MAXPATHLEN);
/* hui 4/16 add cast */
if ((char *)getwd(new->dir.current_dir) == NULL)
XtError("Cannot find current directory!");
}
XswDirUpdate(new);
XtVaGetValues(new->dir.label_w, XtNwidth, &width, NULL);
XtVaSetValues(new->dir.viewer_w, XtNwidth, width, NULL);
XtCallCallbacks((Widget) new, XtNdirectoryChange, new->dir.current_dir);
}
StringList
XswDirGetEntries(w)
DirWidget w;
{
StringList list;
XswMultiListReturnStruct *lptr;
int i, num;
lptr = XswMultiListShowCurrent(w->dir.list_w);
num = 0;
while (lptr[num].list_index != XSW_LIST_NONE) num++;
XswFreeStringList(w->dir.return_list);
w->dir.return_list = (StringList)XtMalloc(sizeof(String)*(num+1));
for(i=0; i < num; i++) {
w->dir.return_list[i] = XtNewString(lptr[i].string);
}
w->dir.return_list[i] = NULL;
return w->dir.return_list;
}
StringList
XswDirGetEntriesAndClear(w)
DirWidget w;
{
StringList list;
XswMultiListReturnStruct *lptr;
int i, num;
lptr = XswMultiListShowCurrent(w->dir.list_w);
w->dir.cur_selection[0] = 0;
num = 0;
while (lptr[num].list_index != XSW_LIST_NONE) {
XswMultiListUnhighlight(w->dir.list_w, lptr[num].list_index);
num++;
}
XswFreeStringList(w->dir.return_list);
w->dir.return_list = (StringList)XtMalloc(sizeof(String)*(num+1));
for(i=0; i < num; i++) {
w->dir.return_list[i] = XtNewString(lptr[i].string);
}
w->dir.return_list[i] = NULL;
XtFree((char *) lptr);
return w->dir.return_list;
}
void XswDirUpdate(w)
DirWidget w;
{
DoChangeDir(w, NULL);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.