ftp.nice.ch/pub/next/unix/developer/pcn.2.0.s.tar.gz#/contrib/gauge/Xsw/Dir.c

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 Marcel Waldvogel and Netfuture.ch.