1 /*****************************************************************************
2 *
3 * xdbx - X Window System interface to the dbx debugger
4 *
5 * Copyright 1989 The University of Texas at Austin
6 * Copyright 1990 Microelectronics and Computer Technology Corporation
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted,
10 * provided that the above copyright notice appear in all copies and that
11 * both that copyright notice and this permission notice appear in
12 * supporting documentation, and that the name of The University of Texas
13 * and Microelectronics and Computer Technology Corporation (MCC) not be
14 * used in advertising or publicity pertaining to distribution of
15 * the software without specific, written prior permission. The
16 * University of Texas and MCC makes no representations about the
17 * suitability of this software for any purpose. It is provided "as is"
18 * without express or implied warranty.
19 *
20 * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
21 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
23 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
24 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
25 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 *
28 * Author: Po Cheung
29 * Created: March 10, 1989
30 *
31 *****************************************************************************
32 *
33 * xxgdb - X Window System interface to the gdb debugger
34 *
35 * Copyright 1990,1993 Thomson Consumer Electronics, Inc.
36 *
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted,
39 * provided that the above copyright notice appear in all copies and that
40 * both that copyright notice and this permission notice appear in
41 * supporting documentation, and that the name of Thomson Consumer
42 * Electronics (TCE) not be used in advertising or publicity pertaining
43 * to distribution of the software without specific, written prior
44 * permission. TCE makes no representations about the suitability of
45 * this software for any purpose. It is provided "as is" without express
46 * or implied warranty.
47 *
48 * TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
49 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
50 * SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
51 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
52 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
53 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 * SOFTWARE.
55 *
56 * Adaptation to GDB: Pierre Willard
57 * XXGDB Created: December, 1990
58 *
59 *****************************************************************************/
60
61 /* dialog.c
62 *
63 * Create the dialogue window where the user enter dbx commands, and
64 * provide action procs to make a text widget behave like a terminal.
65 *
66 * InsertSpace(): Prevent user from deleting past the prompt (action proc
67 * for DELETE or BACKSPACE).
68 * DeleteWord(): Word delete in dialog window. (action proc for Ctrl-w).
69 * DeleteLine(): Line delete in dialog window. (action proc for Ctrl-u).
70 * Dispatch(): Send an input command line to dbx. (action proc for CR).
71 * SigInt(): Send SIGINT to dbx (action proc for Ctrl-C).
72 * SigEof(): Send an EOF signal to dbx (action proc for Ctrl-D).
73 * SigQuit(): Send SIGQUIT to dbx (action proc for Ctrl-\).
74 * CreateDialogWindow(): Create dialog window and install action table.
75 * AppendDialogText(): Append string to dialog window.
76 */
77
78 #include <signal.h>
79 #include "global.h"
80
81 #define DIALOGSIZE 100000 /* max size of dialogue window buffer */
82
83 Widget dialogWindow; /* text window as a dbx terminal */
84 Boolean FalseSignal = FALSE; /* set to TRUE before self-generated
85 interrupt/quit signals */
86 static char DialogText[DIALOGSIZE]; /* text buffer for widget */
87 static XawTextPosition StartPos; /* starting position of input text */
88
89
90 /* This procedure prevents the user from deleting past the prompt, or
91 * any text appended by AppendDialogText() to the dialog window.
92 * It checks the last position of text, if it matches StartPos, set
93 * by AppendDialogText(), it inserts a space so that delete-previous-
94 * character() can only delete the space character.
95 */
96 /* ARGSUSED */
InsertSpace(w,event,params,num_params)97 static void InsertSpace(w, event, params, num_params)
98 Widget w;
99 XEvent *event;
100 String *params;
101 Cardinal *num_params;
102 {
103 XawTextBlock textblock;
104 XawTextPosition lastPos;
105
106 if (XawTextGetInsertionPoint(w) <= StartPos) {
107 lastPos = TextGetLastPos(w);
108 if (lastPos == StartPos) {
109 textblock.firstPos = 0;
110 textblock.length = 1;
111 textblock.ptr = " ";
112 XawTextReplace(w, lastPos, lastPos, &textblock);
113 XawTextSetInsertionPoint(w, lastPos+1);
114 }
115 }
116 }
117
118 /* Erases the preceding word.
119 * Simulates the action of the WERASE character (ctrl-W).
120 */
121 /* ARGSUSED */
DeleteWord(w,event,params,num_params)122 void DeleteWord(w, event, params, num_params)
123 Widget w;
124 XEvent *event;
125 String *params;
126 Cardinal *num_params;
127 {
128 XawTextBlock textblock;
129 XawTextPosition pos;
130 Cardinal i;
131
132 textblock.firstPos = 0;
133 textblock.length = 1;
134 textblock.ptr = " ";
135
136 pos = XawTextGetInsertionPoint(w);
137 if (pos <= StartPos)
138 pos = TextGetLastPos(w);
139 for (i=pos; i > StartPos && DialogText[i-1] == ' '; i--);
140 for (; i > StartPos && DialogText[i-1] != ' '; i--);
141 XawTextReplace(w, i, pos, &textblock);
142 XawTextSetInsertionPoint(w, i);
143 }
144
145 /* Erases the preceding word.
146 * Simulates the action of the WERASE character (ctrl-W).
147 */
148 /* ARGSUSED */
DeleteChar(w,event,params,num_params)149 void DeleteChar(w, event, params, num_params)
150 Widget w;
151 XEvent *event;
152 String *params;
153 Cardinal *num_params;
154 {
155 XawTextBlock textblock;
156 XawTextPosition pos;
157
158 textblock.firstPos = 0;
159 textblock.length = 1;
160 textblock.ptr = " ";
161
162 pos = XawTextGetInsertionPoint(w);
163 if (pos > StartPos) {
164 XawTextReplace(w, pos-1, pos, &textblock);
165 XawTextSetInsertionPoint(w, pos-1);
166 }
167 }
168
169
170 /* Deletes the entire current input line.
171 * simulates the action of the KILL character (ctrl-U).
172 */
173 /* ARGSUSED */
DeleteLine(w,event,params,num_params)174 void DeleteLine(w, event, params, num_params)
175 Widget w;
176 XEvent *event;
177 String *params;
178 Cardinal *num_params;
179 {
180 XawTextBlock textblock;
181 XawTextPosition pos, beginPos;
182 Cardinal i;
183 char *s;
184
185 textblock.firstPos = 0;
186 textblock.length = 1;
187 textblock.ptr = " ";
188
189 pos = XawTextGetInsertionPoint(w);
190 if (w == dialogWindow) {
191 s = DialogText;
192 beginPos = StartPos;
193 if (pos <= beginPos)
194 pos = TextGetLastPos(w);
195 } else {
196 return;
197 }
198 for (i=pos; i > beginPos && s[i-1] != '\n'; i--);
199 XawTextReplace(w, i, pos, &textblock);
200 XawTextSetInsertionPoint(w, i);
201 }
202
203
204 /* Dispatch() is invoked on every <CR>.
205 * It collects text from the dialog window and sends it to dbx.
206 * If the string is a command to dbx (Prompt would be TRUE),
207 * it is stored in the global variable, Command.
208 */
209 /* ARGSUSED */
Dispatch(w,event,params,num_params)210 static void Dispatch(w, event, params, num_params)
211 Widget w;
212 XEvent *event;
213 String *params;
214 Cardinal *num_params;
215 {
216 #ifdef GDB
217 /*
218 For GDB, '\n' means exec previous command again.
219 default command is space+CR, so that we never send
220 CR to gdb (the repeat is managed here)
221 */
222 static char gdb_command[LINESIZ] = " \n";
223 #endif
224 char s[LINESIZ];
225
226 strcpy(s, DialogText + StartPos);
227 #if 1
228 /* (PW)18DEC90 : bug xdbx : without the following line,
229 xdbx sends several times the same lines when Prompt is false */
230 StartPos = TextGetLastPos(dialogWindow);
231 #endif
232
233 if (Prompt)
234 {
235 #ifdef GDB
236 /* When we send \n to gdb, it executes the last command,
237 so better tell xxgdb what gdb is doing */
238 if (strcmp(s, "\n"))
239 strcpy(gdb_command,s); /* if not "\n" ! */
240 else
241 {
242 /* copy previous command in new command, and
243 echo the command in the dialog window. */
244 strcpy(s,gdb_command);
245 AppendDialogText(gdb_command);
246 }
247 #endif /* GDB */
248 send_command (s);
249 }
250 else
251 /* this string is for the application, not for gdb */
252 write_dbx(s);
253 }
254
255 /* Sends an interrupt signal, SIGINT, to dbx.
256 * Simulates the action of the INTR character (ctrl-C).
257 */
signal_interrupt_dbx()258 void signal_interrupt_dbx()
259 {
260 #ifndef GDB
261 FalseSignal = TRUE;
262 #ifdef SYSV /* (PW)13AUG92: change SVR4 into SYSV */ /* (MJH) */
263 kill(-(dbxpid), SIGINT);
264 #else
265 killpg(dbxpid, SIGINT);
266 #endif /* SYSV */
267 #else
268 write_dbx("\003"); /* (PW)18FEB91 : seems to work better */
269 #endif /* GDB */
270 }
271
272 /* Sends an interrupt signal, SIGINT, to dbx.
273 * Simulates the action of the INTR character (ctrl-C).
274 */
275 /* ARGSUSED */
SigInt(w,event,params,num_params)276 static void SigInt(w, event, params, num_params)
277 Widget w;
278 XEvent *event;
279 String *params;
280 Cardinal *num_params;
281 {
282 signal_interrupt_dbx ();
283 }
284
285 /* Sends an EOF signal to dbx. (ctrl-D) */
286 /* ARGSUSED */
SigEof(w,event,params,num_params)287 static void SigEof(w, event, params, num_params)
288 Widget w;
289 XEvent *event;
290 String *params;
291 Cardinal *num_params;
292 {
293 write_dbx("\04");
294 }
295
296
297 /* Sends a QUIT signal, SIGQUIT, to dbx.
298 * Simulates the action of the QUIT character (ctrl-\)
299 */
300 /* ARGSUSED */
SigQuit(w,event,params,num_params)301 static void SigQuit(w, event, params, num_params)
302 Widget w;
303 XEvent *event;
304 String *params;
305 Cardinal *num_params;
306 {
307 FalseSignal = TRUE;
308
309 #ifdef SYSV /* (PW)13AUG92: change SVR4 into SYSV */ /* (MJH) */
310 kill(-(dbxpid), SIGQUIT);
311 #else
312 killpg(dbxpid, SIGQUIT);
313 #endif /* SYSV */
314 }
315
316
317 /*
318 * Dialog window has its own set of translations for editing.
319 * Special action procedures for keys Delete/Backspace, Carriage Return,
320 * Ctrl-U, Ctrl-C, Ctrl-D, Ctrl-\, and word selection.
321 */
CreateDialogWindow(parent)322 void CreateDialogWindow(parent)
323 Widget parent;
324 {
325 Arg args[MAXARGS];
326 Cardinal n;
327
328 static XtActionsRec dialog_actions[] = {
329 {"SigInt", (XtActionProc) SigInt},
330 {"SigEof", (XtActionProc) SigEof},
331 {"SigQuit", (XtActionProc) SigQuit},
332 {"InsertSpace", (XtActionProc) InsertSpace},
333 {"Dispatch", (XtActionProc) Dispatch},
334 {"DeleteChar", (XtActionProc) DeleteChar},
335 {NULL, NULL}
336 };
337
338 static String translations = "#override\n\
339 Ctrl<Key>C: SigInt()\n\
340 Ctrl<Key>D: SigEof()\n\
341 Ctrl<Key>|: SigQuit()\n\
342 Ctrl<Key>W: DeleteWord()\n\
343 Ctrl<Key>U: DeleteLine()\n\
344 Ctrl<Key>H: DeleteChar()\n\
345 <Key>Delete: DeleteChar()\n\
346 <Key>BackSpace: DeleteChar()\n\
347 <Key>Return: newline()Dispatch()\n\
348 ";
349
350 n = 0;
351 XtSetArg(args[n], XtNuseStringInPlace, True); n++;
352 XtSetArg(args[n], XtNstring, (XtArgVal) DialogText); n++;
353 XtSetArg(args[n], XtNlength, (XtArgVal) DIALOGSIZE); n++;
354 XtSetArg(args[n], XtNeditType, (XtArgVal) XawtextAppend); n++;
355 XtSetArg(args[n], XtNscrollVertical, XawtextScrollAlways); n++;
356 XtSetArg(args[n], XtNwrap, XawtextWrapWord); n++;
357 dialogWindow = XtCreateManagedWidget("dialogWindow", asciiTextWidgetClass,
358 parent, args, n );
359 XtOverrideTranslations(dialogWindow, XtParseTranslationTable(translations));
360 XtAppAddActions(app_context, dialog_actions, XtNumber(dialog_actions));
361 }
362
363 #if 0 /* never used */
364 static void TextSetLastPos(w, lastPos)
365 Widget w;
366 XawTextPosition lastPos;
367 {
368 TextWidget ctx = (TextWidget) w;
369 ctx->text.lastPos = lastPos;
370 }
371 #endif
372
AppendDialogText(s)373 void AppendDialogText(s)
374 char *s;
375 {
376 XawTextPosition i, lastPos;
377 XawTextBlock textblock, nullblock;
378
379 if (!s || !strcmp(s, "")) return;
380
381 if (debug) {
382 fprintf(stderr, "AppendDialogText \"%s\"\n", s);
383 }
384
385 textblock.firstPos = 0;
386 textblock.length = strlen(s);
387 textblock.ptr = s;
388
389 lastPos = TextGetLastPos(dialogWindow);
390 if (textblock.length > DIALOGSIZE) {
391 bell(0);
392 #ifdef GDB
393 fprintf(stderr, "xxgdb error: cannot display string in dialogue window\n\
394 string has %d bytes; dialogue window size limit is %d bytes\n",
395 textblock.length, DIALOGSIZE);
396 #else
397 fprintf(stderr, "xdbx error: cannot display string in dialogue window\n\
398 string has %d bytes; dialogue window size limit is %d bytes\n",
399 textblock.length, DIALOGSIZE);
400 #endif
401 return;
402 }
403 if (lastPos + textblock.length > DIALOGSIZE) {
404 nullblock.firstPos = 0;
405 nullblock.length = 0;
406 nullblock.ptr = "";
407
408 i = textblock.length - (DIALOGSIZE - lastPos);
409 if (i < 0.9*DIALOGSIZE)
410 i += 0.1*DIALOGSIZE;
411 while (DialogText[i] != '\n') i++;
412 XawTextReplace(dialogWindow, 0, i+1, &nullblock);
413 lastPos = TextGetLastPos(dialogWindow);
414 }
415 XawTextReplace(dialogWindow, lastPos, lastPos, &textblock);
416 StartPos = TextGetLastPos(dialogWindow);
417 XawTextSetInsertionPoint(dialogWindow, StartPos);
418
419 #if 0 /* no longer necessary I think */
420 /* fix annoying bug that dialog mark is sometimes scrolled off bottom (widget bug?) */
421 XawTextDisplay(dialogWindow);
422 #endif
423
424 #if defined(OLDSUNOS)||defined(SUNOS4)
425 /* Have experienced bug where dialog window actually writes off bottom
426 (does not scroll to bottom). Seems more prevalent with Openwindows,
427 but since it needs to debug certain programs to get this to show up.
428 Couldn't find the problem, but this works around it: (really icky but
429 only way I found to fix it) */
430
431 if (StartPos >= ((TextWidget)dialogWindow)->text.lt.info[((TextWidget)dialogWindow)->text.lt.lines].position)
432 XtCallActionProc(dialogWindow, "redraw-display", 0, 0, 0);
433 #endif /* SUNOS */
434 }
435
436