v08i109: xdbx -- Dbx for X11, Part05/07
Po Cheung
cheung%SW.MCC.COM at MCC.COM
Tue Aug 28 18:04:25 AEST 1990
Submitted-by: cheung%SW.MCC.COM at MCC.COM (Po Cheung)
Posting-number: Volume 8, Issue 109
Archive-name: xdbx/part05
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 5 (of 7)."
# Contents: command.c source.c
# Wrapped by cheung at espresso.sw.mcc.com on Fri Aug 24 03:24:51 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'command.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'command.c'\"
else
echo shar: Extracting \"'command.c'\" \(18726 characters\)
sed "s/^X//" >'command.c' <<'END_OF_FILE'
X/*****************************************************************************
X *
X * xdbx - X Window System interface to the dbx debugger
X *
X * Copyright 1989 The University of Texas at Austin
X * Copyright 1990 Microelectronics and Computer Technology Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of The University of Texas
X * and Microelectronics and Computer Technology Corporation (MCC) not be
X * used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission. The
X * University of Texas and MCC makes no representations about the
X * suitability of this software for any purpose. It is provided "as is"
X * without express or implied warranty.
X *
X * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author: Po Cheung
X * Created: March 10, 1989
X *
X *****************************************************************************/
X
X/* command.c
X *
X * Create the command window, the command buttons and their callbacks.
X *
X * CreateCommandPanel() : Create a window with command buttons
X * CreateButtons() : Create command buttons in panel
X * AddButton() : Add a command button into the command window
X * ButtonSet() : Action proc for command button translation
X *
X * Command callbacks for the command buttons:
X *
X * forwardSearch() : forward string search
X * reverseSearch() : reverse string search
X * Search() : call either forwardSearch() or reverseSearch()
X * PopupSearch() : command callback for search button
X * DoneSearch() : command callback for DONE button in search panel
X * CreateSearchPopup() : create search panel
X *
X * Command queue manipulation routines:
X * send_command(): send a command to dbx and record in the queue
X * get_command(): read command off head of queue
X * insert_command(): insert command at the head of queue
X * delete_command(): delete command from head of queue
X */
X
X#include <signal.h>
X#include <ctype.h>
X#include <sys/wait.h>
X#include "global.h"
X
X#define REVERSE 0
X#define FORWARD 1
X
XWidget commandWindow; /* command panel with buttons */
XBoolean PopupMode = False;
Xstatic int Button;
Xstatic Widget searchPopupShell, searchPopup;
Xstatic Widget AddButton();
Xstatic Widget button[30];
Xstatic char SearchString[BUFSIZ] = ""; /* search string buffer */
Xstatic char command[LINESIZ];
Xstatic CommandRec *commandQueue = NULL;
X#ifdef BSD
Xstatic char savedCommand[LINESIZ] = "";
X#endif
X
X/* ARGSUSED */
Xstatic void ButtonSet(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X Button = atoi(params[0]);
X}
X
X/* ARGSUSED */
X/* Execute the dbx command specifed in client_data
X */
Xstatic void DoIt (w, command, call_data)
X Widget w;
X XtPointer command;
X XtPointer call_data;
X{
X /* run, cont, next, step, where, up, down, status */
X send_command(command);
X AppendDialogText(command);
X}
X
X/* ARGSUSED */
Xstatic void Return (w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *funcname;
X int nbytes;
X
X funcname = XFetchBytes(display, &nbytes); /* from CUT_BUFFER0 */
X if (nbytes == 0)
X strcpy(command, "return\n");
X else
X sprintf(command, "return %s\n", funcname);
X send_command(command);
X AppendDialogText(command);
X}
X
X/* ARGSUSED */
Xstatic void Stop_at(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X XawTextPosition pos;
X int line;
X
X if (displayedFile == NULL) {
X UpdateMessageWindow(STOP_AT_HELP, NULL);
X bell(0);
X return;
X }
X pos = XawTextGetInsertionPoint(sourceWindow);
X line = TextPositionToLine(pos);
X sprintf(command, "stop at %d\n", line);
X send_command(command);
X AppendDialogText(command);
X}
X
X/* ARGSUSED */
Xstatic void Stop_in(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *funcname;
X int nbytes;
X
X funcname = XFetchBytes(display, &nbytes); /* from CUT_BUFFER0 */
X if (nbytes == 0) {
X UpdateMessageWindow(STOP_IN_HELP, NULL);
X bell(0);
X return;
X }
X sprintf(command, "stop in %s\n", funcname);
X send_command(command);
X AppendDialogText(command);
X}
X
X
X/* Delete removes the stop_no associated with a given line number.
X * RemoveStop() is called to undisplay the stop sign only when there
X * are no more stop_no's associated with that line number.
X */
X/* ARGSUSED */
Xstatic void Delete(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X XawTextPosition pos;
X char *string;
X int stop_no, line, nbytes;
X
X string = XFetchBytes(display, &nbytes);
X if (nbytes > 0 && (stop_no = atoi(string)) > 0) {
X sprintf(command, "delete %d\n", stop_no);
X send_command(command);
X AppendDialogText(command);
X return;
X }
X else if (displayedFile) {
X pos = XawTextGetInsertionPoint(sourceWindow);
X line = TextPositionToLine(pos);
X if (stop_no = LineToStop_no(line)) {
X sprintf(command, "delete %d\n", stop_no);
X send_command(command);
X AppendDialogText(command);
X return;
X }
X }
X UpdateMessageWindow(DELETE_HELP, NULL);
X bell(0);
X}
X
X/* ARGSUSED */
Xstatic void Print(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *string;
X int nbytes;
X
X if (Button == 3) PopupMode = True;
X
X string = XFetchBytes(display, &nbytes);
X if (nbytes == 0) {
X UpdateMessageWindow(PRINT_HELP, NULL);
X bell(0);
X return;
X }
X if (client_data == (XtPointer)0)
X sprintf(command, "print %s\n", string);
X else if (client_data == (XtPointer)1)
X sprintf(command, "print *%s\n", string);
X send_command(command);
X AppendDialogText(command);
X}
X
X/* ARGSUSED */
Xstatic void Func(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *funcname;
X int nbytes;
X
X funcname = XFetchBytes(display, &nbytes);
X if (nbytes == 0)
X strcpy(command, "func\n");
X else
X sprintf(command, "func %s\n", funcname);
X send_command(command);
X AppendDialogText(command);
X}
X
X/* ARGSUSED */
Xstatic void Quit(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X union wait status;
X
X write_dbx("quit\n");
X XtDestroyApplicationContext(app_context);
X kill(dbxpid, SIGKILL);
X wait3(&status, WNOHANG, NULL);
X exit(0);
X}
X
X
X/* ARGSUSED */
Xstatic void Display_(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *string;
X int nbytes;
X
X string = XFetchBytes(display, &nbytes);
X sprintf(command, "display %s\n", string);
X send_command(command);
X AppendDialogText(command);
X}
X
X
X/* ARGSUSED */
Xstatic void Undisplay(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *string;
X int stop_no, nbytes;
X
X string = XFetchBytes(display, &nbytes);
X if (nbytes == 0) {
X UpdateMessageWindow(UNDISPLAY_HELP, NULL);
X bell(0);
X return;
X }
X if ((stop_no = atoi(string)) > 0)
X sprintf(command, "undisplay %d\n", stop_no);
X else
X sprintf(command, "undisplay %s\n", string);
X send_command(command);
X AppendDialogText(command);
X}
X
X
X/* ARGSUSED */
Xstatic void Dump(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X char *funcname;
X int nbytes;
X
X funcname = XFetchBytes(display, &nbytes);
X if (nbytes == 0)
X strcpy(command, "dump\n");
X else
X sprintf(command, "dump %s\n", funcname);
X send_command(command);
X AppendDialogText(command);
X}
X
X
X/* Beginning from startpos, this routine searches text forward for
X * searchstring, and returns 1 if searchstring is found, also returning
X * the left and right positions of the matched string in left and right;
X * else 0 is returned.
X * It also does wrap-around search.
X */
Xstatic forwardSearch(text, startpos, searchstring, left, right)
X char *text;
X int startpos;
X char *searchstring;
X XawTextPosition *left, *right;
X{
X int searchlength, searchsize, i, n=0;
X char *s1, *s2;
X
X searchlength = strlen(searchstring);
X searchsize = strlen(text) - searchlength;
X for (i=startpos; i < searchsize; i++) {
X n = searchlength;
X s1 = &text[i];
X s2 = searchstring;
X while (--n >= 0 && *++s1 == *s2++);
X if (n < 0) break;
X }
X if (n < 0) {
X *left = i+1;
X *right = i+1+searchlength;
X return 1;
X }
X else {
X for (i=0; i < startpos; i++) {
X n = searchlength;
X s1 = &text[i];
X s2 = searchstring;
X while (--n >= 0 && *++s1 == *s2++);
X if (n < 0) break;
X }
X if (n < 0) {
X *left = i+1;
X *right = i+1+searchlength;
X return 1;
X }
X return 0;
X }
X}
X
X
X/* Similar to forwardSearch(), except that it does a reverse search
X */
Xstatic reverseSearch(text, startpos, searchstring, left, right)
X char *text;
X XawTextPosition startpos;
X char *searchstring;
X XawTextPosition *left, *right;
X{
X int searchlength, i, n=0;
X char *s1, *s2;
X
X searchlength = strlen(searchstring);
X for (i=startpos; i > searchlength; i--) {
X n = searchlength;
X s1 = &text[i];
X s2 = &searchstring[searchlength-1];
X while (--n >= 0 && *--s1 == *s2--);
X if (n < 0) break;
X }
X if (n < 0) {
X *right = i;
X *left = *right-searchlength;
X return 1;
X }
X else {
X for (i=strlen(text)-1; i > startpos; i--) {
X n = searchlength;
X s1 = &text[i];
X s2 = &searchstring[searchlength-1];
X while (--n >= 0 && *--s1 == *s2--);
X if (n < 0) break;
X }
X if (n < 0) {
X *right = i;
X *left = *right-searchlength;
X return 1;
X }
X return 0;
X }
X}
X
X/* ARGSUSED */
Xstatic void PopupSearch(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X Arg args[MAXARGS];
X Cardinal n;
X Dimension popup_width, dialog_width;
X Position x, y;
X
X if (!displayedFile) {
X UpdateMessageWindow(SEARCH_HELP, NULL);
X bell(0);
X }
X else {
X XtRealizeWidget(searchPopupShell);
X n = 0;
X XtSetArg(args[n], XtNwidth, &popup_width); n++;
X XtGetValues(searchPopupShell, args, n);
X n = 0;
X XtSetArg(args[n], XtNwidth, &dialog_width); n++;
X XtGetValues(dialogWindow, args, n);
X XtTranslateCoords(dialogWindow,
X (Position)(dialog_width - popup_width)/2, 10, &x, &y);
X n = 0;
X XtSetArg(args[n], XtNx, x); n++;
X XtSetArg(args[n], XtNy, y); n++;
X XtSetValues(searchPopupShell, args, n);
X XtPopup(searchPopupShell, XtGrabNone);
X }
X}
X
X
X/* ARGSUSED */
X/* This routine handles both forward and reverse text search.
X * If no text has been entered, the contents of the cut buffer are used
X * for searching.
X */
Xstatic void Search(w, direction, call_data)
X Widget w;
X XtPointer direction;
X XtPointer call_data;
X{
X XawTextBlock textblock;
X XawTextPosition pos, left, right;
X char *searchString;
X
X searchString = XawDialogGetValueString(searchPopup);
X if (strlen(searchString) == 0) {
X textblock.ptr = XFetchBytes(display, &textblock.length);
X if (!textblock.ptr) {
X UpdateMessageWindow("No search string selected", NULL);
X bell(0);
X return;
X }
X searchString = textblock.ptr;
X }
X pos = XawTextGetInsertionPoint(sourceWindow);
X if ((direction == (XtPointer)FORWARD &&
X forwardSearch(displayedFile->buf, pos, searchString, &left, &right)) ||
X (direction == (XtPointer)REVERSE &&
X reverseSearch(displayedFile->buf, pos, searchString, &left, &right))) {
X AdjustText(TextPositionToLine(left));
X XawTextSetSelection(sourceWindow, left, right);
X XawTextSetInsertionPoint(sourceWindow, left);
X }
X else {
X if (direction == (XtPointer)FORWARD)
X UpdateMessageWindow("String not found", NULL);
X else if (direction == (XtPointer)REVERSE)
X UpdateMessageWindow("String not found", NULL);
X else
X UpdateMessageWindow("xdbx error: illegal search direction", NULL);
X bell(0);
X }
X}
X
X/* ARGSUSED */
Xstatic void DoneSearch(w, client_data, call_data)
X Widget w;
X XtPointer client_data;
X XtPointer call_data;
X{
X XtPopdown(client_data);
X}
X
X/* ARGSUSED */
Xstatic void Activate(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X Search(w, (XtPointer)FORWARD, NULL);
X DoneSearch(w, (XtPointer)searchPopupShell, NULL);
X}
X
Xstatic void CreateSearchPopup()
X{
X Widget dialogValue;
X Arg args[MAXARGS];
X Cardinal n;
X
X static XtActionsRec search_actions[] = {
X {"Activate", Activate},
X {NULL, NULL}
X };
X
X static String translations = "#override\n\
X <Key>Return: Activate() \n\
X ";
X
X n = 0;
X XtSetArg(args[n], XtNinput, True); n++;
X XtSetArg(args[n], XtNallowShellResize, True); n++;
X searchPopupShell = XtCreatePopupShell("Search", transientShellWidgetClass,
X toplevel, args, n);
X
X n = 0;
X XtSetArg(args[n], XtNlabel, "Enter search string :"); n++;
X XtSetArg(args[n], XtNvalue, SearchString); n++;
X searchPopup = XtCreateManagedWidget("searchPopup", dialogWidgetClass,
X searchPopupShell, args, n);
X
X AddButton(searchPopup, "<<", Search, (XtPointer) REVERSE);
X AddButton(searchPopup, ">>", Search, (XtPointer) FORWARD);
X AddButton(searchPopup, "DONE", DoneSearch, (XtPointer)searchPopupShell);
X
X dialogValue = XtNameToWidget(searchPopup, "value");
X XtOverrideTranslations(dialogValue, XtParseTranslationTable(translations));
X XtAppAddActions(app_context, search_actions, XtNumber(search_actions));
X}
X
X
X
Xstatic Widget AddButton(parent, name, function, client_data)
XWidget parent;
Xchar *name;
Xvoid (*function) ();
XXtPointer client_data; /* callback registered data */
X{
X Widget button;
X Arg args[MAXARGS];
X Cardinal n;
X
X static XtActionsRec command_actions[] = {
X {"ButtonSet", (XtActionProc) ButtonSet},
X {NULL, NULL}
X };
X
X static String translations = "\
X <EnterWindow>: highlight() \n\
X <LeaveWindow>: reset() \n\
X <Btn1Down>: set()\n\
X <Btn1Up>: ButtonSet(1) notify() unset() \n\
X <Btn3Down>: set()\n\
X <Btn3Up>: ButtonSet(3) notify() unset()\n\
X ";
X
X n = 0;
X XtSetArg(args[n], XtNresize, (XtArgVal) False); n++;
X if (strcmp(name, "print") == NULL || strcmp(name, "print *") == NULL) {
X XtSetArg(args[n], XtNtranslations,
X XtParseTranslationTable(translations)); n++;
X }
X button = XtCreateManagedWidget(name, commandWidgetClass, parent, args, n);
X XtAddCallback(button, XtNcallback, function, client_data);
X XtAppAddActions(app_context, command_actions, XtNumber(command_actions));
X return (button);
X}
X
X
Xstatic void CreateButtons (parent)
XWidget parent;
X{
X int i=0;
X
X button[i++] = AddButton (parent, "run", DoIt, "run\n");
X button[i++] = AddButton (parent, "cont", DoIt, "cont\n");
X button[i++] = AddButton (parent, "next", DoIt, "next\n");
X button[i++] = AddButton (parent, "step", DoIt, "step\n");
X#ifdef BSD
X button[i++] = AddButton (parent, "return", Return, "return\n");
X#endif
X button[i++] = AddButton (parent, "stop at", Stop_at, NULL);
X button[i++] = AddButton (parent, "stop in", Stop_in, NULL);
X button[i++] = AddButton (parent, "delete", Delete, NULL);
X button[i++] = AddButton (parent, "where", DoIt, "where\n");
X button[i++] = AddButton (parent, "up", DoIt, "up\n");
X button[i++] = AddButton (parent, "down", DoIt, "down\n");
X button[i++] = AddButton (parent, "print", Print, (XtPointer)0);
X button[i++] = AddButton (parent, "print *", Print, (XtPointer)1);
X button[i++] = AddButton (parent, "func", Func, NULL);
X button[i++] = AddButton (parent, "file", File, NULL);
X button[i++] = AddButton (parent, "status", DoIt, "status\n");
X#ifndef BSD
X button[i++] = AddButton (parent, "display", Display_, NULL);
X button[i++] = AddButton (parent, "undisplay", Undisplay, NULL);
X#endif
X button[i++] = AddButton (parent, "dump", Dump, NULL);
X button[i++] = AddButton (parent, "search", PopupSearch, NULL);
X button[i++] = AddButton (parent, "quit", Quit, NULL);
X button[i++] = NULL;
X CreateSearchPopup();
X}
X
X
X/* Create a command widget, and the buttons. */
X
Xvoid CreateCommandPanel(parent)
XWidget parent;
X{
X Arg args[10];
X Cardinal n;
X
X n = 0;
X commandWindow = XtCreateManagedWidget("commandWindow", boxWidgetClass,
X parent, args, n);
X CreateButtons(commandWindow);
X getwd(cwd);
X}
X
X/**************************************************************************
X *
X * Command queue functions
X *
X **************************************************************************/
X
X/* Append command to end of the command queue and send the command to dbx */
X
Xvoid send_command(command)
Xchar *command;
X{
X CommandRec *p, *q, *r;
X
X#ifdef BSD
X /* Save the command if it is not a blank command; else use the
X last saved command instead */
X if (strcspn(command, " \n"))
X strcpy(savedCommand, command);
X else
X strcpy(command, savedCommand);
X#endif
X
X p = (CommandRec *)XtNew(CommandRec);
X p->command = XtNewString(command);
X p->next = NULL;
X if (!commandQueue)
X commandQueue = p;
X else {
X q = commandQueue;
X while (r = q->next)
X q = r;
X q->next = p;
X }
X write_dbx(command);
X}
X
X/* Read command at the head of the command queue */
X
Xchar *get_command()
X{
X if (commandQueue) {
X return (commandQueue->command);
X }
X else
X return NULL;
X}
X
X/* Delete command from the head of the command queue */
X
Xvoid delete_command()
X{
X CommandRec *p;
X
X if (p = commandQueue) {
X commandQueue = p->next;
X XtFree(p->command);
X XtFree(p);
X }
X}
X
X/* Insert command into head of queue */
X
Xvoid insert_command(command)
Xchar *command;
X{
X CommandRec *p;
X
X p = (CommandRec *)XtNew(CommandRec);
X p->command = XtNewString(command);
X p->next = NULL;
X if (!commandQueue)
X commandQueue = p;
X else {
X p->next = commandQueue;
X commandQueue = p;
X }
X}
END_OF_FILE
if test 18726 -ne `wc -c <'command.c'`; then
echo shar: \"'command.c'\" unpacked with wrong size!
fi
# end of 'command.c'
fi
if test -f 'source.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source.c'\"
else
echo shar: Extracting \"'source.c'\" \(19496 characters\)
sed "s/^X//" >'source.c' <<'END_OF_FILE'
X/*****************************************************************************
X *
X * xdbx - X Window System interface to the dbx debugger
X *
X * Copyright 1989 The University of Texas at Austin
X * Copyright 1990 Microelectronics and Computer Technology Corporation
X *
X * Permission to use, copy, modify, and distribute this software and its
X * documentation for any purpose and without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and that
X * both that copyright notice and this permission notice appear in
X * supporting documentation, and that the name of The University of Texas
X * and Microelectronics and Computer Technology Corporation (MCC) not be
X * used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission. The
X * University of Texas and MCC makes no representations about the
X * suitability of this software for any purpose. It is provided "as is"
X * without express or implied warranty.
X *
X * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X *
X * Author: Po Cheung
X * Created: March 10, 1989
X *
X *****************************************************************************/
X
X/* source.c
X *
X * Create the source window and handle display of file.
X *
X * source_init(): Initialization routine.
X * Update(): Action proc to update source window on scrollbar action.
X * NotifyResize(): Action proc to update source window on resize.
X * CreateSourceWindow(): Create the source window.
X * BuildLinePos(): Build an array of starting text position of each line.
X * LookUpFileTable():Check out source file info from a file table.
X * SaveDisplayedFileInfo(): records displayed file info into file table.
X * DisplayFile(): Display a file on the source window
X * LoadFile(): Search for a file and open it for display.
X */
X
X#include <X11/Xos.h>
X#include <sys/stat.h>
X#include <pwd.h>
X#include "global.h"
X
X#define MAXDIRS 256 /* max number of dirs in dirList */
X
Xchar CurrentFile[MAXNAME]; /* current contents of file variable */
XWidget sourceForm, /* parent of sourceWindow */
X sourceWindow; /* text window for source file */
XFileRec *displayedFile; /* pointer to table entry of currently
X displayed file */
X
Xstatic FileRec **fileTable; /* table of file records */
Xstatic int fileTableSize; /* size of file table */
Xstatic char *dirList[MAXDIRS]; /* list of dirs for searching files */
X
Xvoid source_init()
X{
X dirList[0] = NULL;
X}
X
X/*
X * Update topline, bottomline, arrow sign, updown sign, stop signs, and
X * line label.
X */
X/* ARGSUSED */
Xvoid Update(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X XawTextPosition pos;
X int topline;
X FileRec *file;
X
X if (displayedFile) {
X file = displayedFile;
X pos = XawTextTopPosition(sourceWindow);
X file->topPosition = pos;
X topline = TextPositionToLine(pos);
X /* Update the symbols only if the text scrolls */
X if (file->topline != topline) {
X file->topline = topline;
X file->bottomline = MIN (file->topline + file->lines - 1,
X file->lastline);
X XawTextSetInsertionPoint(sourceWindow, file->linepos[file->topline]);
X UpdateLineLabel(file->topline);
X UpdateStops(file);
X UpdateArrow(file);
X UpdateUpdown(file);
X UpdateBomb(file);
X }
X else {/* Update caret position only */
X pos = XawTextGetInsertionPoint(sourceWindow);
X UpdateLineLabel(TextPositionToLine(pos));
X }
X }
X}
X
X/*
X * Update bottomline, arrow sign, updown sign and stop signs on resize.
X * Invoked by ConfigureNotify event.
X */
X/* ARGSUSED */
Xstatic void NotifyResize(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X XawTextPosition pos;
X TextWidget ctx = (TextWidget) sourceWindow;
X FileRec *file;
X
X if (file = displayedFile) {
X file->lines = ctx->text.lt.lines;
X pos = XawTextTopPosition(sourceWindow);
X file->topline = TextPositionToLine(pos);
X file->bottomline = MIN (file->topline + file->lines - 1,
X file->lastline);
X UpdateStops(file);
X UpdateArrow(file);
X UpdateUpdown(file);
X UpdateBomb(file);
X }
X}
X
X/* Update the position of the caret */
X/* ARGSUSED */
X#ifdef notdef
Xvoid UpdateLine(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X XawTextPosition pos;
X int line;
X
X pos = XawTextGetInsertionPoint(w);
X line = TextPositionToLine(pos);
X UpdateLineLabel(line);
X}
X#endif
X
X/* My select-start routine that cancels the effect of automatic scrolling
X * near the bottom of an Athena text widget window.
X */
X/* ARGSUSED */
Xvoid SelectStart(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X XawTextPosition topPosition;
X
X /* remember the top display position before automatic scrolling */
X /* displayedFile->topPosition = XawTextTopPosition(w); */
X topPosition = XawTextTopPosition(w);
X
X XtCallActionProc(w, "select-start", event, params, num_params);
X
X /* reset to remembered position if top position changed */
X /* if (XawTextTopPosition(w) != displayedFile->topPosition)
X TextSetTopPosition(w, displayedFile->topPosition); */
X if (XawTextTopPosition(w) != topPosition)
X TextSetTopPosition(w, topPosition);
X}
X
X/* My select-end routine to store the text selection into both the PRIMARY
X * selection and cut buffer 0.
X */
X/* ARGSUSED */
Xvoid SelectEnd(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X XawTextPosition begin, end, start;
X Widget textsrc;
X XawTextBlock buffer;
X char s[10000];
X int nchars;
X
X XawTextGetSelectionPos(w, &begin, &end);
X XawTextSetSelection(w, begin, end);
X if (begin == end) return;
X textsrc = XawTextGetSource(w);
X strcpy(s, "");
X for (start=begin, nchars=end-begin; nchars > 0;
X start=begin+buffer.length, nchars-=buffer.length) {
X XawTextSourceRead(textsrc, start, &buffer, nchars);
X strncat(s, buffer.ptr, buffer.length);
X }
X XStoreBytes(display, s, strlen(s));
X}
X
X/* This is my own select word routine to replace the standard action
X * procedure provided by the Text widget.
X * It selects a word delimited by DELIMITERS, not whitespace.
X */
X/* ARGSUSED */
Xvoid SelectWord(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X XawTextPosition pos, left, right, start;
X XawTextBlock buffer;
X Widget textsrc;
X char s[LINESIZ];
X char *p, *ls, *rs;
X int nchars;
X
X pos = XawTextGetInsertionPoint(w);
X textsrc = XawTextGetSource(w);
X
X XawTextSourceRead(textsrc, pos, &buffer, 1);
X if (buffer.length == 0 || (buffer.length == 1 &&
X strchr(app_resources.delimiters, (int)*(buffer.ptr)) != NULL)) {
X XStoreBytes(display, NULL, 0);
X return;
X }
X
X left = XawTextSourceScan(textsrc, pos+1, XawstWhiteSpace, XawsdLeft, 1,
X FALSE);
X right = XawTextSourceScan(textsrc, left, XawstWhiteSpace, XawsdRight, 1,
X FALSE);
X
X strcpy(s, "");
X for (start=left, nchars=right-left; nchars > 0;
X start=left+buffer.length, nchars-=buffer.length) {
X XawTextSourceRead(textsrc, start, &buffer, nchars);
X strncat(s, buffer.ptr, buffer.length);
X }
X
X if (!strcmp(s, "")) return;
X p = s+pos-left;
X ls = (char *) strtok(s, app_resources.delimiters);
X rs = (char *) strtok(NULL, app_resources.delimiters);
X if (!ls) return;
X while (rs<=p && rs!=NULL) {
X ls = rs;
X rs = (char *) strtok(NULL, app_resources.delimiters);
X }
X left = left + ls - s;
X right = left + strlen(ls) - 1;
X
X XawTextUnsetSelection(w);
X XStoreBytes(display, ls, strlen(ls));
X XawTextSetSelection(w, left, right+1);
X}
X
X/* Print the value of the expression in cut buffer 0. */
X/* ARGSUSED */
Xvoid PrintSelection(w, event, params, num_params)
X Widget w;
X XEvent *event;
X String *params;
X Cardinal *num_params;
X{
X char command[LINESIZ];
X char *string;
X int nbytes;
X
X string = XFetchBytes(display, &nbytes);
X if (nbytes == 0) {
X UpdateMessageWindow(PRINT_HELP, NULL);
X bell(0);
X return;
X }
X sprintf(command, "print %s\n", string);
X send_command(command);
X AppendDialogText(command);
X}
X
X/*
X * On top of a form widget, we have a text widget with scrollbar, label
X * widgets for the stop sign, arrow sign, and updown signs.
X */
Xvoid CreateSourceWindow(parent)
XWidget parent;
X{
X TextWidget ctx;
X Arg args[MAXARGS];
X Cardinal n;
X
X static XtActionsRec sbar_actions[] = {
X {"NotifyResize", NotifyResize},
X {"Update", Update},
X {NULL, NULL}
X };
X
X static String sbarTranslations = "\
X <Configure>: NotifyResize() \n\
X <Btn2Down>: StartScroll(Continuous) MoveThumb() NotifyThumb() \
X Update() \n\
X <Btn2Motion>: MoveThumb() NotifyThumb() Update() \n\
X <BtnUp>: NotifyScroll(Proportional) EndScroll() Update() \n\
X ";
X
X n = 0;
X XtSetArg(args[n], XtNdefaultDistance, 0); n++;
X sourceForm = XtCreateManagedWidget("sourceForm", formWidgetClass,
X parent, args, n);
X
X n = 0;
X XtSetArg(args[n], XtNborderWidth, 0); n++;
X XtSetArg(args[n], XtNtype, (XtArgVal)XawAsciiFile); n++;
X XtSetArg(args[n], XtNstring, (XtArgVal)"/dev/null"); n++;
X XtSetArg(args[n], XtNscrollVertical, (XtArgVal) XawtextScrollAlways);n++;
X sourceWindow = XtCreateManagedWidget("sourceWindow", asciiTextWidgetClass,
X sourceForm, args, n);
X
X ctx = (TextWidget) sourceWindow;
X if (ctx->text.vbar)
X XtOverrideTranslations(ctx->text.vbar,
X XtParseTranslationTable(sbarTranslations));
X XtAppAddActions(app_context, sbar_actions, XtNumber(sbar_actions));
X}
X
X
X/*
X * Build the array which gives the starting text position of each line.
X * > Estimate the number of lines in the file and allocate memory buffer.
X * > Starting position of line #1 is 0, and is stored in linepos[1].
X * > Search for '\n' till end of buffer.
X */
Xstatic void BuildLinePos(file)
XFileRec *file;
X{
X char *p;
X int line, nlines;
X
X nlines = MAX(1, file->filesize/CHARS_PER_LINE);
X file->linepos = (XawTextPosition *)
X XtMalloc ((nlines+2) * sizeof(XawTextPosition));
X p = file->buf;
X line = 0;
X file->linepos[line++] = 0;
X file->linepos[line++] = 0;
X while (*p) {
X if (*p++ == '\n') {
X if (line == nlines) { /* buffer full, need more memory */
X file->linepos = (XawTextPosition *) XtRealloc (file->linepos,
X (nlines + ADD_LINES) * sizeof(XawTextPosition));
X nlines += ADD_LINES;
X }
X file->linepos[line++] = p - file->buf;
X }
X }
X file->lastline = line - 2;
X file->linepos = (XawTextPosition *) XtRealloc /* shrink to min size */
X (file->linepos, line * sizeof(XawTextPosition));
X}
X
X
X/*
X * Look up the file table for an entry with "filename"
X * If not found, create an entry and initialize proper fields,
X * else, return pointer to entry found.
X */
Xstatic LookUpFileTable(pathname, filename, file)
Xchar *pathname, *filename;
XFileRec **file;
X{
X struct stat fileinfo;
X int fd;
X int i, j, n;
X
X for (i=0; fileTable && fileTable[i] && i<fileTableSize; i++) {
X if (strcmp(fileTable[i]->pathname, pathname) == NULL) { /* file found */
X if (stat(pathname, &fileinfo) == -1) {
X UpdateMessageWindow("Error: cannot stat file %s", pathname);
X *file = fileTable[i];
X return 0;
X }
X if (fileinfo.st_mtime > fileTable[i]->mtime) { /* file modified */
X XtFree((char *)fileTable[i]->buf);
X XtFree((char *)fileTable[i]->linepos);
X XtFree((char *)fileTable[i]);
X displayedFile = NULL;
X break;
X }
X else if (displayedFile && /* same as displayed file */
X strcmp(pathname, displayedFile->pathname) == 0) {
X *file = NULL;
X return 0;
X }
X else {
X *file = fileTable[i];
X return 0;
X }
X }
X }
X
X /* Record file into file table */
X
X if (i == fileTableSize) { /* file table full, enlarge it */
X fileTableSize += ADD_SIZE;
X fileTable = (FileRec **)
X XtRealloc (fileTable, fileTableSize * sizeof(FileRec *));
X for (j=i; j<fileTableSize; j++)
X fileTable[j] = NULL;
X }
X if ((fd = open(pathname, O_RDONLY)) == -1) {
X UpdateMessageWindow("Error: cannot open file %s", pathname);
X return -1;
X }
X if (fstat(fd, &fileinfo) == -1) {
X UpdateMessageWindow("Error: cannot fstat file %s", pathname);
X close(fd);
X return -1;
X }
X fileTable[i] = (FileRec *) XtMalloc (sizeof(FileRec));
X fileTable[i]->filesize = fileinfo.st_size + 1;
X fileTable[i]->mtime = fileinfo.st_mtime;
X fileTable[i]->buf = XtMalloc((int)fileTable[i]->filesize);
X if ((n = read(fd, fileTable[i]->buf, (int) fileTable[i]->filesize)) == -1) {
X UpdateMessageWindow("Error: cannot read file %s", pathname);
X XtFree(fileTable[i]->buf);
X XtFree(fileTable[i]);
X fileTable[i] = NULL;
X close(fd);
X return -1;
X }
X fileTable[i]->buf[n] = '\0';
X fileTable[i]->pathname = XtNewString(pathname);
X fileTable[i]->filename = XtNewString(filename);
X fileTable[i]->currentline = 1;
X fileTable[i]->topline = 1;
X fileTable[i]->bottomline = 0;
X fileTable[i]->topPosition = 0;
X BuildLinePos(fileTable[i]);
X close(fd);
X *file = fileTable[i];
X return 0;
X}
X
X/*
X * Remember file position and current line before closing.
X */
Xstatic void SaveDisplayedFileInfo()
X{
X XawTextPosition pos;
X
X if (displayedFile) {
X displayedFile->topPosition = XawTextTopPosition(sourceWindow);
X pos = XawTextGetInsertionPoint(sourceWindow);
X displayedFile->currentline = TextPositionToLine(pos);
X }
X}
X
X
X/* DisplayFile() displays the file onto the source window. It
X * uses topPosition to remember where it was last opened. But it
X * must recalculate bottomline because the window size might be
X * different.
X */
Xstatic void DisplayFile(file)
XFileRec *file;
X{
X Arg args[MAXARGS];
X Cardinal n;
X TextWidget ctx = (TextWidget) sourceWindow;
X
X n = 0;
X XtSetArg(args[n], XtNdisplayPosition, (XtArgVal)file->topPosition); n++;
X XtSetArg(args[n], XtNstring, (XtArgVal) file->pathname); n++;
X XtSetArg(args[n], XtNeditType, (XtArgVal) XawtextRead); n++;
X XtSetValues(sourceWindow, args, n);
X file->lines = ctx->text.lt.lines;
X file->bottomline = MIN (file->topline + file->lines - 1, file->lastline);
X}
X
X
X/* Given a filename starting with a tilde (`~'), it expands ~[user] to
X * the home directory of that user, or to the login home directory if user
X * is not specified.
X */
Xstatic char *expand(filename)
Xchar *filename;
X{
X struct passwd *pwd;
X char *string, *name, newfile[MAXNAME];
X
X string = XtNewString(filename+1);
X if (*string == '\0' || *string == '/')
X name = (char *) getlogin();
X else
X name = (char *) strtok(string, "/");
X if (name == NULL)
X return filename;
X pwd = (struct passwd *) getpwnam(name);
X if (pwd && pwd->pw_dir) {
X sprintf(newfile, "%s%s", pwd->pw_dir, filename+strlen(name)+1);
X return XtNewString(newfile);
X }
X else
X return filename;
X}
X
X
X/* Create a list of directories for searching source files.
X * It reads the list of directories specified by the user, adding
X * the current directory into the list if it is not already there.
X *
X * With fix from Dave Gagne (daveg at fs1.ee.ubc.ca) 7/30/90
X */
Xvoid MakeDirList(output)
Xchar *output;
X{
X char *s, list[BUFSIZ], command[LINESIZ];
X int i, use_cwd;
X
X for (i=0; dirList[i]; i++) /* remove old list */
X XtFree(dirList[i]);
X i = 0;
X use_cwd = TRUE;
X if (output) { /* create list */
X s = (char *) strtok(output, " \n");
X while (s) {
X dirList[i] = XtNewString(s);
X
X if (dirList[i][0] == '~') /* expand '~' */
X dirList[i] = expand(dirList[i]);
X if (LASTCH(dirList[i]) == '/') /* remove last '/' */
X LASTCH(dirList[i]) = '\0';
X if (strcmp(dirList[i], ".") == NULL) /* watch for "." */
X use_cwd = FALSE;
X
X ++i;
X s = (char *) strtok(NULL, " \n");
X }
X dirList[i] = NULL;
X }
X
X if (use_cwd) { /* include current dir */
X dirList[i++] = XtNewString(".");
X dirList[i] = NULL;
X }
X strcpy(list, ""); /* tell dbx our new list */
X for (i=0; dirList[i]; i++) {
X strcat(list, dirList[i]);
X strcat(list, " ");
X }
X sprintf(command, "use %s\n", list);
X Parse = False;
X query_dbx(command);
X}
X
X
X/* Returns the full pathname of a given file.
X * It searches for the file from a list of directories.
X */
Xchar *GetPathname(filename)
Xchar *filename;
X{
X char pathname[LINESIZ];
X int i;
X
X if (filename == NULL || strcmp(filename, "") == NULL)
X return NULL;
X for (i=0; dirList[i]; i++) {
X if (*filename == '/' && access(filename, R_OK) == -1) {
X /* this handles the exceptional case of sun4 dbx output */
X strcpy(filename, &filename[1]);
X }
X if (*filename == '/' || *filename == '~')
X strcpy(pathname, filename);
X else if (strcmp(dirList[i], ".") == NULL)
X sprintf(pathname, "%s/%s", cwd, filename);
X else if (*dirList[i] == '/' || *dirList[i] == '~')
X sprintf(pathname, "%s/%s", dirList[i], filename);
X else
X sprintf(pathname, "%s/%s/%s", cwd, dirList[i], filename);
X if (access(pathname, R_OK) == 0)
X return XtNewString(pathname);
X }
X UpdateMessageWindow("File not found: %s", filename);
X return NULL;
X}
X
X/*
X * Given a file name, LoadFile attempts to open it and displays it onto
X * the source window:
X * 1. get the full pathname of the file
X * 2. LookUpFileTable() returns a pointer to the file's entry if it's
X * already in the table; else, creates an entry and return a pointer.
X * 3. save the current displayedFile info
X * 4. display the file
X * 5. update the file label and the various signs on the source window.
X * LoadFile returns 0 upon successful completion, -1 otherwise.
X */
Xint LoadFile(filename)
Xchar *filename;
X{
X FileRec *file;
X char *pathname;
X
X pathname = GetPathname(filename);
X if (pathname == NULL) {
X return -1;
X }
X if (LookUpFileTable(pathname, filename, &file) != -1) {
X if (file) { /* load new file */
X SaveDisplayedFileInfo();
X DisplayFile(file);
X UpdateFileLabel(pathname);
X XawTextUnsetSelection(sourceWindow);
X XawTextSetInsertionPoint(sourceWindow, file->linepos[file->currentline]);
X UpdateLineLabel(file->currentline);
X UpdateStops(file);
X UpdateArrow(file);
X UpdateUpdown(file);
X UpdateBomb(file);
X displayedFile = file;
X }
X return 0;
X }
X else { /* LookUpFileTable() fails */
X return -1;
X }
X}
X
Xint LoadCurrentFile()
X{
X query_dbx("file\n");
X return LoadFile(CurrentFile);
X}
END_OF_FILE
if test 19496 -ne `wc -c <'source.c'`; then
echo shar: \"'source.c'\" unpacked with wrong size!
fi
# end of 'source.c'
fi
echo shar: End of archive 5 \(of 7\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 7 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list