/*****************************************************************************
*
* 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
*
*****************************************************************************
*
* xxgdb - X Window System interface to the gdb debugger
*
* Copyright 1990,1993 Thomson Consumer Electronics, Inc.
*
* 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 Thomson Consumer
* Electronics (TCE) not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. TCE makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
* TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
* SHALL TCE 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.
*
* Adaptation to GDB: Pierre Willard
* XXGDB Created: December, 1990
*
*****************************************************************************/
/* filemenu.c
*
* Construct a file menu (directory browser) which allows a user to go
* up and down the directory tree, to select text files to display, and
* to select executable files to debug. 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 <ctype.h>
#include <X11/Xos.h>
#include <sys/stat.h>
#ifdef SYSV
#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <dirent.h>
#ifdef _POSIX_SOURCE
#ifndef S_IFDIR
#define S_IFDIR 0040000 /* directory */
#endif
#ifndef S_IEXEC
#define S_IEXEC 00100 /* execute/search permission, owner */
#endif
#endif /* _POSIX_SOURCE */
#else /* SYSV */
#if defined(SUNOS4) || defined(__FreeBSD__)
#include <dirent.h>
#else
#include <sys/dir.h>
#endif
#endif /* SYSV */
#include "global.h"
#define MAXCOLUMNS 8 /* max number of columns in file menu */
#define FILES_PER_COL 10 /* # of files per column in file menu */
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 */
void File();
static void UpdateFileMenu();
/* Change working directory to 'dir'.
* For Berkeley dbx, modify static global variable, cwd, to keep track of
* current working directory.
* For Sun dbx, change working directory of dbx.
*/
static void changeDir(dir)
char *dir;
{
char command[LINESIZ];
char store[LINESIZ];
int i,j;
if(!strcmp(dir, "./")) return;
#if defined(BSD)
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';
}
#else /* not BSD */
if(!strcmp(dir,"../"))
{
for(i=0,j=0; cwd[i]; i++) if(cwd[i]=='/')j++;
if( j == 1 ) strcpy(store,"/");
else
strcpy(store,"..");
}
else
{
if(!strcmp(cwd, "/"))cwd[0]='\0';
sprintf(store,"%s/%s", cwd, dir);
LASTCH(store)='\0';
}
sprintf(command, "cd %s\n", store);
#ifdef GDB
/* because silly gdb 4.0 displays nothing with cd command when
confirm is on (possibly a gdb bug) , I just reset confirm to on
just for this command !. */
if (new_gdb4())
query_gdb("set confirm on\n", PARSE_OFF | ECHO_OFF | FILTER_OFF);
query_gdb(command, PARSE_ON | ECHO_OFF | FILTER_OFF);
if (new_gdb4()) /* reset confirm to off */
query_gdb("set confirm off\n", PARSE_OFF | ECHO_OFF | FILTER_OFF);
#else
query_dbx(command);
#endif /* not GDB */
#endif /* BSD */
}
/* 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
*/
#if !defined(SYSV) && !defined(__FreeBSD__)
static int InList(entry)
Directory *entry;
{
char pathname[LINESIZ];
struct stat statbuf;
if (strcmp(entry->d_name, ".") == 0 || /* ignore current directory */
LASTCH(entry->d_name) == '~' || /* 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, "/");
++(entry->d_namlen);
return True;
}
if (statbuf.st_mode & S_IEXEC) { /* is executable */
strcat(entry->d_name, "*");
++(entry->d_namlen);
return True;
}
return True;
}
#endif /* not SYSV */
/* 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 void ScanDir(dir)
char *dir;
{
#if !defined(SYSV) && !defined(__FreeBSD__)
extern alphasort();
Directory **namelist;
#else
struct dirent *WorkingDirEntry;
DIR *WorkingDir;
char store[LINESIZ];
#endif
register int i,j;
#if defined(SYSV) || defined(__FreeBSD__)
if(!(WorkingDir = opendir(dir)))
{
UpdateMessageWindow("scandir: cannot open %s", dir);
return;
}
nfiles=0;
while(readdir(WorkingDir))nfiles++;
rewinddir(WorkingDir);
#else
nfiles = scandir(dir, &namelist, InList, alphasort);
if (nfiles == -1) {
UpdateMessageWindow("scandir: cannot open %s", dir);
return;
}
#endif
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++) {
#if defined(SYSV) || defined(__FreeBSD__)
WorkingDirEntry = readdir(WorkingDir);
if(!strcmp(WorkingDirEntry->d_name, "."))
strcpy(store, "./");
else
{
if(!strcmp(WorkingDirEntry->d_name, ".."))
strcpy(store, "../");
else
{
struct stat statbuf;
sprintf(store,"%s/%s",cwd,WorkingDirEntry->d_name);
if(stat(store, &statbuf) == -1)
store[0]='\0';
else
{
if (statbuf.st_mode & S_IFDIR)
sprintf(store, "%s/", WorkingDirEntry->d_name);
else
if (statbuf.st_mode & S_IEXEC)
sprintf(store, "%s*", WorkingDirEntry->d_name);
else
if(LASTCH(WorkingDirEntry->d_name) == '~' ||
LASTCH(WorkingDirEntry->d_name) == '#' ||
WorkingDirEntry->d_name[0] == '.' ||
(LASTCH(WorkingDirEntry->d_name) == 'o' &&
SECLASTCH(WorkingDirEntry->d_name) == '.'))
store[0]='\0';
else
strcpy(store, WorkingDirEntry->d_name);
}
}
}
if(store[0])
filelist[i++] = XtNewString(store);
#else /* not SYSV */
filelist[i++] = XtNewString(namelist[j]->d_name);
XtFree((XtPointer) namelist[j]);
#endif
}
filelist[i++] = NULL;
#if defined(SYSV) || defined(__FreeBSD__)
closedir(WorkingDir);
#else
XtFree((XtPointer) namelist);
#endif
return;
}
/* Callback for the fileMenu list widget.
* > if the selected item is a directory, display contents of that directory.
* > (Sun dbx only) if the selected item is an executable file, issue the
* debug command.
* > if the selected item is a readable file, display the file.
*/
/* ARGSUSED */
static void DisplayMenuFile(w, popupshell, call_data)
Widget w;
Widget popupshell;
XawListReturnStruct *call_data;
{
char string[LINESIZ], *filename, command[LINESIZ];
XtPopdown(popupshell);
filename = call_data->string;
if (filename == NULL) return;
if (LASTCH(filename) == '/') {
changeDir(filename);
XtDestroyWidget(popupshell);
UpdateFileMenu(); /* create new menu */
File(); /* pop it up */
}
else if (LASTCH(filename) == '*') {
UpdateMessageWindow("",NULL);
#ifdef GDB
strcpy(string, filename);
LASTCH(string) = '\0';
/* for GDB 4.xx, we send the command : file */
if (new_gdb4())
sprintf(command, "file %s\n", string);
else
{
/* for GDB 3.xx, we send the commands : exec-file & symbol-file */
/* (PW)21DEC90 : this button is special because it has to send
TWO commands to GDB. */
sprintf(command, "exec-file %s\n", string);
send_command(command);
AppendDialogText(command);
sprintf(command, "symbol-file %s\n", string);
}
send_command(command);
AppendDialogText(command);
#else
#ifndef BSD
strcpy(string, filename);
LASTCH(string) = '\0';
sprintf(command, "debug %s\n", string);
send_command(command);
AppendDialogText(command);
#endif
#endif /* GDB */
}
else {
UpdateMessageWindow("",NULL);
#ifdef GDB
if (strcmp(filename, "core") == 0)
sprintf(command, "core-file %s\n", filename);
else
sprintf(command, "list %s:1\n", filename);
send_command(command);
AppendDialogText(command);
#else /* not GDB */
sprintf(command, "file %s\n", filename);
send_command(command);
AppendDialogText(command);
#endif /* GDB */
}
}
/* Callback to popdown the file menu
*/
/* ARGSUSED */
static void CancelFileMenu(w, popupshell, call_data)
Widget w;
Widget popupshell;
caddr_t call_data;
{
XtPopdown(popupshell);
UpdateMessageWindow("",NULL);
}
/* 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 void SetUpFileMenu(dir)
char *dir;
{
Widget cancelButton;
Arg args[MAXARGS];
Cardinal n;
char menulabel[LINESIZ];
int ncolumns;
n = 0;
popupshell = XtCreatePopupShell("File Directory", transientShellWidgetClass,
toplevel, args, n);
n = 0;
popup = XtCreateManagedWidget("popup", panedWidgetClass, popupshell,
args, n);
ScanDir(dir);
strcpy(fileMenuDir, dir);
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);
}
/* 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 void UpdateFileMenu()
{
SetUpFileMenu(cwd);
#ifdef GDB
query_gdb_directories(); /* defined in gdb_handler.c */
#else
query_dbx("use\n");
#endif /* GDB */
}
/* File command button callback.
*/
/* ARGSUSED */
void File(w, client_data, call_data)
Widget w;
caddr_t client_data;
caddr_t call_data;
{
Arg args[MAXARGS];
Cardinal n;
Position x, y, x_offset;
Dimension fileMenu_width, fileMenuLabel_width, border_width,
width, dialog_width;
XDefineCursor(display, XtWindow(toplevel), watch);
XDefineCursor(display, XtWindow(sourceWindow), watch);
XDefineCursor(display, XtWindow(dialogWindow), watch);
XFlush(display);
if (strcmp(fileMenuDir, cwd))
UpdateFileMenu();
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);
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);
XtPopup(popupshell, XtGrabNonexclusive);
UpdateMessageWindow("Select a file or directory",NULL);
XUndefineCursor(display, XtWindow(toplevel));
XUndefineCursor(display, XtWindow(sourceWindow));
XUndefineCursor(display, XtWindow(dialogWindow));
}
syntax highlighted by Code2HTML, v. 0.9.1