cheung%SW.MCC.COM@MCC.COM (Po Cheung) (08/28/90)
Submitted-by: cheung%SW.MCC.COM@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@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@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@sun.com / argv@ora.com Opinions expressed reflect those of the author only.