/*
* xmail - X window system interface to the mail program
*
* Copyright 1990,1991,1992 by National Semiconductor Corporation
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose is hereby granted without fee, 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 National Semiconductor Corporation not
* be used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
* SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
* WITHOUT EXPRESS OR IMPLIED WARRANTY. NATIONAL SEMICONDUCTOR CORPORATION
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
* EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION 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: Michael C. Wagnitz - National Semiconductor Corporation
*
*/
#include "global.h"
#include <sys/stat.h>
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
#ifdef USE_DIRENT
#include <dirent.h>
#else
#include <sys/dir.h>
#endif
/*
** @(#)SetDirectory() - Create popup list of directory folder names
*/
/* ARGSUSED */
void
SetDirectory(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
int depth, label_width, n, total, x, y;
char buf[BUFSIZ], tmp[BUFSIZ], trans[BUFSIZ];
String ep, name, path, s, List, *ftbl;
Widget menu, layout, bw, above, to_left;
Arg args[8];
DIR *dirp;
struct stat st_buf;
#ifdef USE_DIRENT
struct dirent *dp;
#else
struct direct *dp;
#endif
static String dir_Trans = "<Btn1Down>: SetDirectory(%s, %s, %d)";
static String m_Trans = "<Leave>: MenuPopdown(%s)";
static String b_Trans = "<Enter>: set()\n<Leave>: unset()\n<Btn3Up>: MyNotify(%d) MenuPopdown(%s)";
static XtCallbackRec callbacks[] = {
{ (XtCallbackProc) GetFolderName, NULL },
{ NULL, NULL }
};
name = params[0];
path = params[1];
(void) sscanf(params[2], "%d", &depth);
depth += 1;
label_width = 0;
/*
** To avoid problems later on with XtNameToWidget, don't create a
** menu if the name contains either a dot (.) or an asterisk (*).
*/
for (s = name; *s; s++)
if (strchr(".*", *s) != NULL) break;
menu = XtNameToWidget(w, name);
if (*s == '\0' && menu == NULL) { /* no dot or asterisk and no menu yet */
SetCursor(WATCH);
(void) sprintf(trans, m_Trans, name);
XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(trans));
menu = XtCreatePopupShell(name, overrideShellWidgetClass, w, args, ONE);
XtSetArg(args[0], XtNdefaultDistance, 1);
layout = XtCreateManagedWidget("menu", formWidgetClass, menu, args, ONE);
/*
** Copy folder names into a list
*/
n = BUFSIZ; /* start with a BUFSIZ block */
List = (String) XtMalloc((unsigned) n);
List[0] = '\0';
if ((dirp = opendir(path)) == NULL)
XtError("xmail cannot access directory name passed to SetDirectory()");
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
if (dp->d_name[0] != '.') { /* skip parent and dot files */
if ((int)strlen(List) + (int)strlen(dp->d_name) + 2 >= n) {
n += BUFSIZ;
List = (String) XtRealloc(List, (unsigned) n);
}
if (List[0]) (void) strcat(List, " ");
(void) strcat(List, dp->d_name);
}
(void) closedir(dirp);
List = (String) XtRealloc(List, (unsigned) strlen(List) + 2);
if (List[0]) { /* if directory isn't empty... */
/*
** Store pointers to folder names in a table array for sorting
*/
for (total=1, s=List; *s; s++) /* count number of names in the List */
if (*s == ' ') total++; /* (increase the folder name count) */
ftbl = (String *) XtMalloc((unsigned) (total + 2) * sizeof(String *));
x = n = 0;
ep = &List[(int)strlen(List)]; /* Find the end of this array */
for (s = List; s < ep; s++) { /* stuff word pointers into a table */
while ((s+n < ep) && *(s+n) != ' ') n++;
if (s+n < ep) *(s+n) = '\0'; /* mark off the end of this name */
ftbl[x++] = s; /* save this pointer in our table */
s += n; /* find start of next folder name */
n = 0;
}
ftbl[x] = NULL; /* NULL terminate our table */
/*
** (quick) sort our table into ascending alphabetical order
*/
if (total > 1)
qsort((char *)ftbl, total, sizeof(char *), str_compare);
/*
** Then, determine label width by finding longest entry in our table
*/
for (x = n = 0; n < total && ftbl[n]; n++)
if ((int)strlen(ftbl[n]) > (int)strlen(ftbl[x])) x = n;
label_width = XTextWidth(XMail.buttonFont, ftbl[x], strlen(ftbl[x]));
}
if (label_width) {
(void) sprintf(trans, b_Trans, depth, name);
XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(trans));
XtSetArg(args[1], XtNwidth, label_width + 12);
XtSetArg(args[2], XtNfont, XMail.buttonFont);
XtSetArg(args[3], XtNcallback, callbacks);
/*
** create the menu buttons
*/
bw = above = to_left = NULL;
for (x = 0; x < total; x++) {
(void) sprintf(buf, "%s/%s", path, ftbl[x]);
(void) strncpy(tmp, ftbl[x], BUFSIZ);
/*
** If this folder is also a directory, add a trailing slash '/'
*/
if (stat(buf, &st_buf) == 0) /* IF exists and is readable */
if (S_ISDIR(st_buf.st_mode) && LASTCH(tmp) != '/')
(void) strcat(tmp, "/"); /* If a directory mark it so */
XtSetArg(args[4], XtNlabel, tmp);
XtSetArg(args[5], XtNfromHoriz, to_left);
if (! to_left) /* (else keep current value) */
XtSetArg(args[6], XtNfromVert, above);
bw = XtCreateManagedWidget("menubutton",commandWidgetClass,layout,args,7);
if (to_left == NULL) above = bw;
if ((x+1) % 3 == 0) /* make box three items wide */
to_left = NULL;
else to_left = bw;
if (LASTCH(tmp) != '/')
AddInfoHandler(bw, Folder_Info[1]);
else {
/*
** This is a directory. Add a button popup menu for its files.
*/
(void) sprintf(trans, dir_Trans, tmp, buf, depth);
XtOverrideTranslations(bw, XtParseTranslationTable(trans));
AddInfoHandler(bw, Folder_Info[2]);
}
} /* end - for each name in the folder table */
} /* end - if there exists at least one folder name */
/*
** If no buttons were created for this menu, destroy the widget.
*/
if (! label_width)
XtDestroyWidget(menu);
SetCursor(NORMAL);
XtFree((String) ftbl);
XtFree((String) List);
} /* end - if menu had not yet been created */
/*
** If menu exists, pop it up, after setting x,y coordinates
*/
menu = XtNameToWidget(w, name);
if (! menu || menu->core.being_destroyed)
XBell(XtDisplay(toplevel), 33);
else {
SetPopup(w, event, params, num_params);
/*
** Mark folders with new messages by changing the background Pixmap
*/
SetNewness(XtNameToWidget(menu, "*menu"), path);
XtSetArg(args[0], XtNy, &y);
XtGetValues(menu, args, ONE);
y -= XMail.menuY; /* don't offset menu below cursor */
XtSetArg(args[0], XtNy, y);
XtSetValues(menu, args , ONE);
XtPopup(menu, XtGrabNone);
}
} /* SetDirectory */
syntax highlighted by Code2HTML, v. 0.9.1