7b4ac7e1 |
1 | /* Interface from GDB to X windows. |
4187119d |
2 | Copyright (C) 1987, 1989 Free Software Foundation, Inc. |
7b4ac7e1 |
3 | |
4187119d |
4 | This file is part of GDB. |
7b4ac7e1 |
5 | |
4187119d |
6 | GDB is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 1, or (at your option) |
9 | any later version. |
7b4ac7e1 |
10 | |
4187119d |
11 | GDB is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GDB; see the file COPYING. If not, write to |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
7b4ac7e1 |
19 | |
20 | /* Original version was contributed by Derek Beatty, 30 June 87. */ |
21 | |
7a67dd45 |
22 | #include <stdio.h> |
7b4ac7e1 |
23 | #include "defs.h" |
7b4ac7e1 |
24 | #include "param.h" |
25 | #include "symtab.h" |
26 | #include "frame.h" |
27 | |
3bf57d21 |
28 | #include <X11/IntrinsicP.h> |
29 | #include <X11/StringDefs.h> |
7b4ac7e1 |
30 | #include <X11/Label.h> |
7b4ac7e1 |
31 | #include <X11/Command.h> |
e91b87a3 |
32 | #include <X11/AsciiText.h> |
3bf57d21 |
33 | #include <X11/Box.h> |
34 | #include <X11/VPaned.h> |
7b4ac7e1 |
35 | |
7b4ac7e1 |
36 | |
e91b87a3 |
37 | /*#define XtNfunction "function"*/ |
38 | |
7b4ac7e1 |
39 | /* Cursor used in GDB window. */ |
40 | |
41 | #define gdb_width 16 |
42 | #define gdb_height 16 |
43 | #define gdb_x_hot 7 |
44 | #define gdb_y_hot 0 |
45 | static short gdb_bits[] = { |
46 | 0x0000, 0x0140, 0x0220, 0x0220, |
47 | 0x23e2, 0x13e4, 0x09c8, 0x0ff8, |
48 | 0x0220, 0x3ffe, 0x0630, 0x03e0, |
49 | 0x0220, 0x1ffc, 0x2632, 0x01c0}; |
50 | |
51 | #define gdb_mask_width 16 |
52 | #define gdb_mask_height 16 |
53 | #define gdb_mask_x_hot 7 |
54 | #define gdb_mask_y_hot 0 |
55 | static short gdb_mask_bits[] = { |
56 | 0x0360, 0x07f0, 0x07f0, 0x77f7, |
57 | 0x7fff, 0x7fff, 0x1ffc, 0x1ffc, |
58 | 0x7fff, 0x7fff, 0x7fff, 0x0ff8, |
59 | 0x3ffe, 0x7fff, 0x7fff, 0x7fff}; |
60 | |
61 | /* The X display on which the window appears. */ |
62 | |
e91b87a3 |
63 | Display *screen_display; |
64 | |
65 | #if 0 |
66 | /* The graphics context. */ |
67 | GC default_gc; |
68 | #endif |
7b4ac7e1 |
69 | |
70 | /* Windows manipulated by this package. */ |
71 | |
e91b87a3 |
72 | static Window icon_window; |
3bf57d21 |
73 | static Widget main_widget; |
7b4ac7e1 |
74 | static Widget containing_widget; |
75 | static Widget source_name_widget; |
76 | static Widget source_text_widget; |
77 | static Widget exec_name_widget; |
78 | static Widget button_box_widget; |
79 | |
80 | /* Source text display. */ |
81 | |
82 | static struct symtab *source_window_symtab = 0; |
83 | |
84 | /* Forward declarations */ |
85 | |
86 | static Widget create_text_widget (); |
7b4ac7e1 |
87 | \f |
88 | /* Display an appropriate piece of source code in the source window. */ |
89 | |
90 | xgdb_display_source () |
91 | { |
92 | char *filename; |
e91b87a3 |
93 | static Arg labelArgs[1]; |
7b4ac7e1 |
94 | int linenumbers_changed = 0; |
e91b87a3 |
95 | static int new = 1; |
7b4ac7e1 |
96 | |
97 | struct symtab_and_line get_selected_frame_sal (); |
98 | struct symtab_and_line sal; |
e91b87a3 |
99 | struct frame_info *fi; |
7b4ac7e1 |
100 | |
e91b87a3 |
101 | /* Do nothing if called before we are initialized or when there |
102 | is nothing to show. */ |
7b4ac7e1 |
103 | |
e91b87a3 |
104 | if (!containing_widget || !selected_frame) return; |
7b4ac7e1 |
105 | |
106 | /* Get the symtab and line number of the selected frame. */ |
107 | |
108 | fi = get_frame_info (selected_frame); |
e91b87a3 |
109 | sal = find_pc_line (fi->pc, fi->next_frame); |
7b4ac7e1 |
110 | |
111 | /* Strictly this is wrong, but better than a blank display */ |
112 | |
113 | if (sal.symtab == NULL) |
114 | { |
115 | sal.symtab = current_source_symtab; |
116 | /* current_source_line may be off by a small number like 4 */ |
117 | sal.line = current_source_line; |
118 | } |
119 | |
120 | /* Do a path search and get the exact filename of this source file. |
121 | Also scan it and find its source lines if not already done. */ |
122 | |
123 | if (sal.symtab) |
124 | linenumbers_changed = get_filename_and_charpos (sal.symtab, sal.line, |
125 | &filename); |
126 | |
127 | if (!filename) sal.symtab = NULL; |
128 | |
129 | /* If the source window may be wrong, destroy it (and make a new one). */ |
130 | |
131 | if (linenumbers_changed || source_window_symtab != sal.symtab) |
132 | { |
e91b87a3 |
133 | static Arg fileArgs[1]; |
134 | XtTextSource src; |
135 | new = 1; |
7b4ac7e1 |
136 | source_window_symtab = sal.symtab; |
137 | |
e91b87a3 |
138 | src = XtTextGetSource(source_text_widget); |
139 | XtDiskSourceDestroy(src); |
3bf57d21 |
140 | |
7b4ac7e1 |
141 | XtSetArg (fileArgs[0], XtNfile, filename); |
e91b87a3 |
142 | src = XtDiskSourceCreate(source_text_widget->core.parent, fileArgs, 1); |
143 | XtTextSetSource(source_text_widget, src, 0); |
7b4ac7e1 |
144 | |
145 | XtSetArg (labelArgs[0], XtNlabel, |
146 | filename ? filename : "No source displayed."); |
147 | XtSetValues (source_name_widget, labelArgs, XtNumber (labelArgs)); |
148 | if (filename) free (filename); |
149 | } |
150 | |
151 | /* Update display and cursor positions as necessary. |
152 | Cursor should be placed on line sal.line. */ |
153 | |
e91b87a3 |
154 | { |
155 | static int top_line_number, bottom_line_number; |
156 | int current_top; |
157 | Arg textArgs[1]; |
158 | |
159 | if (! new) |
160 | { |
161 | int new_top; |
162 | |
163 | /* Get positions of start of display, and caret */ |
164 | XtSetArg (textArgs[0], XtNdisplayPosition, NULL); |
165 | XtGetValues (source_text_widget, textArgs, XtNumber (textArgs)); |
166 | new_top = source_charpos_line (source_window_symtab, |
167 | (int) textArgs[0].value); |
168 | bottom_line_number += new_top - top_line_number; |
169 | top_line_number = new_top; |
170 | } |
171 | |
172 | /* If appropriate, scroll the text display. */ |
173 | if (sal.line < top_line_number |
174 | || sal.line > bottom_line_number |
175 | || new) |
176 | { |
177 | /* yes, these magic numbers are ugly, but I don't know how |
178 | * to get the height of a text widget in a V11-portable way |
179 | */ |
180 | top_line_number = (sal.line > 15) ? sal.line - 15 : 0; |
181 | bottom_line_number = top_line_number + 35; |
182 | |
183 | XtSetArg (textArgs[0], XtNdisplayPosition, |
184 | source_line_charpos (source_window_symtab, top_line_number)); |
185 | XtSetValues (source_text_widget, textArgs, XtNumber (textArgs)); |
186 | } |
3bf57d21 |
187 | |
e91b87a3 |
188 | /* Set the text display cursor position within the text. */ |
3bf57d21 |
189 | |
e91b87a3 |
190 | XtSetArg (textArgs[0], XtNinsertPosition, |
191 | source_line_charpos (source_window_symtab, sal.line)); |
192 | XtSetValues (source_text_widget, textArgs, XtNumber (textArgs)); |
193 | } |
7b4ac7e1 |
194 | } |
195 | \f |
196 | /* Display FILENAME in the title bar at bottom of window. */ |
197 | |
198 | xgdb_display_exec_file (filename) |
199 | char *filename; |
200 | { |
201 | static Arg labelArgs[1]; |
202 | |
203 | XtSetArg (labelArgs[0], XtNlabel, filename); |
204 | XtSetValues (exec_name_widget, labelArgs, XtNumber (labelArgs)); |
205 | } |
206 | |
207 | /* Do any necessary prompting, etc. */ |
208 | |
209 | static char *prompt_string; |
210 | |
211 | static void |
212 | print_prompt () |
213 | { |
214 | if (prompt_string) |
e91b87a3 |
215 | printf ("%s", prompt_string); |
4187119d |
216 | fflush (stdout); |
7b4ac7e1 |
217 | } |
218 | |
219 | /* Handlers for buttons. */ |
220 | |
221 | /* Subroutine used by "print" and "print*" buttons. |
222 | STARFLAG is 1 for print*, 0 for print. |
223 | Get the "selection" from X and use it as the operand of a print command. */ |
224 | |
225 | static void |
e91b87a3 |
226 | print_button(w, starflag, call_data) |
227 | Widget w; |
228 | int starflag; |
229 | caddr_t call_data; |
7b4ac7e1 |
230 | { |
231 | int selected_length; |
232 | char *selected_text; |
7b4ac7e1 |
233 | char *cmd = starflag ? "print * " : "print "; |
234 | register int cmdlen = strlen (cmd); |
235 | |
3bf57d21 |
236 | selected_text = XFetchBytes (screen_display, &selected_length); |
7b4ac7e1 |
237 | if (selected_length) |
238 | { |
239 | char *line = xmalloc (cmdlen + selected_length + 1); |
240 | strcpy (line, cmd); |
241 | strncpy (line + cmdlen, selected_text, selected_length); |
242 | line[cmdlen + selected_length] = 0; |
243 | |
244 | execute_command (line, 0); |
245 | |
246 | free (selected_text); |
247 | free (line); |
248 | } |
249 | |
250 | print_prompt (); |
251 | } |
252 | |
7b4ac7e1 |
253 | \f |
254 | /* Subroutine used by "stop at" and "go till" buttons. |
255 | Set a breakpoint at the position indicated by the "selection" |
256 | in the source window, and, if RUNFLAG is nonzero, continue. */ |
257 | |
258 | static void |
e91b87a3 |
259 | breakpoint_button(w, runflag, call_data) |
260 | Widget w; |
261 | int runflag; |
262 | caddr_t call_data; |
7b4ac7e1 |
263 | { |
264 | XtTextPosition start, finish; |
265 | |
3bf57d21 |
266 | XtTextGetSelectionPos (source_text_widget, &start, &finish); |
7b4ac7e1 |
267 | if (!source_window_symtab) |
268 | printf ("No source file displayed.\n"); |
269 | else |
270 | { |
271 | set_breakpoint (source_window_symtab, |
272 | source_charpos_line (source_window_symtab, start), |
273 | runflag); |
274 | if (runflag) |
275 | { |
276 | cont_command (0, 1); |
277 | xgdb_display_source (); |
278 | } |
279 | } |
280 | print_prompt (); |
281 | } |
282 | |
7b4ac7e1 |
283 | /* decide if a character is trash */ |
284 | static int |
285 | garbage (c) |
286 | char c; |
287 | { |
288 | if ('a' <= c && c <= 'z') return 0; |
289 | if ('A' <= c && c <= 'Z') return 0; |
290 | if ('0' <= c && c <= '9') return 0; |
291 | if (c == '_') return 0; |
292 | return 1; |
293 | } |
294 | |
295 | /* Set a breakpoint at the place specified by the "selection" in X. */ |
296 | |
297 | static void |
298 | explicit_breakpoint_button () |
299 | { |
300 | int selected_length; |
301 | char *selected_text; |
302 | |
303 | selected_text = XFetchBytes (screen_display, &selected_length); |
304 | if (selected_length) |
305 | { |
306 | char *line = (char *) xmalloc (selected_length + 6); |
307 | register char *p, *sp, *end; |
308 | |
309 | strcpy (line, "break "); |
310 | |
311 | /* Copy selection but exclude "garbage" characters. */ |
312 | |
313 | p = selected_text; |
314 | end = p + selected_length; |
315 | sp = line + strlen (line); |
316 | |
317 | while (garbage (*p) && p != end) p++; |
318 | while (!garbage (*p) && p != end) |
319 | *sp++ = *p++; |
320 | *sp = 0; |
321 | |
322 | execute_command (line, 0); |
323 | free (selected_text); |
324 | free (line); |
325 | } |
326 | print_prompt (); |
327 | } |
328 | \f |
7b4ac7e1 |
329 | |
330 | static void |
e91b87a3 |
331 | do_command(w, command, call_data) |
332 | Widget w; |
333 | char *command; |
334 | caddr_t call_data; |
7b4ac7e1 |
335 | { |
4187119d |
336 | char *copy = (char *) xmalloc (strlen (command) + 1); |
337 | strcpy (copy, command); |
338 | execute_command (copy, 0); |
7b4ac7e1 |
339 | xgdb_display_source (); |
340 | print_prompt (); |
4187119d |
341 | free (copy); |
7b4ac7e1 |
342 | } |
343 | |
7b4ac7e1 |
344 | static void |
3bf57d21 |
345 | redisplay_button() |
7b4ac7e1 |
346 | { |
e91b87a3 |
347 | xgdb_display_source(); |
7b4ac7e1 |
348 | } |
349 | \f |
350 | /* Define and display all the buttons. */ |
351 | |
352 | static void |
3bf57d21 |
353 | addbutton (parent, name, function, closure) |
e91b87a3 |
354 | Widget parent; |
355 | char *name; |
356 | void (*function) (); |
357 | caddr_t closure; |
7b4ac7e1 |
358 | { |
e91b87a3 |
359 | static XtCallbackRec Callback[] = { |
360 | {NULL, (caddr_t)NULL}, |
361 | {NULL, (caddr_t)NULL}, |
362 | }; |
363 | static Arg commandArgs[] = { |
364 | {XtNlabel, (XtArgVal)NULL}, |
365 | {XtNcallback, (XtArgVal)Callback}, |
366 | }; |
367 | |
368 | Callback[0].callback = (XtCallbackProc)function; |
369 | Callback[0].closure = (caddr_t)closure; |
370 | commandArgs[0].value = (XtArgVal)name; |
371 | XtCreateManagedWidget (name, commandWidgetClass, parent, |
372 | commandArgs, XtNumber(commandArgs)); |
7b4ac7e1 |
373 | } |
374 | |
375 | /* Create the button windows and store them in `buttons'. */ |
376 | |
377 | static void |
378 | create_buttons (parent) |
379 | Widget parent; |
380 | { |
3bf57d21 |
381 | addbutton (parent, "run", do_command, "run"); |
382 | addbutton (parent, "quit", do_command, "quit"); |
383 | |
384 | addbutton (parent, "break in", explicit_breakpoint_button, NULL); |
385 | addbutton (parent, "break at", breakpoint_button, 0); |
386 | addbutton (parent, "go until", breakpoint_button, 1); |
7b4ac7e1 |
387 | |
3bf57d21 |
388 | addbutton (parent, "print", print_button, 0); |
389 | addbutton (parent, "print*", print_button, 1); |
7b4ac7e1 |
390 | |
3bf57d21 |
391 | addbutton (parent, "next", do_command, "next"); |
392 | addbutton (parent, "step", do_command, "step"); |
393 | addbutton (parent, "cont", do_command, "cont"); |
394 | addbutton (parent, "finish", do_command, "finish"); |
7b4ac7e1 |
395 | |
3bf57d21 |
396 | addbutton (parent, "up", do_command, "up"); |
397 | addbutton (parent, "down", do_command, "down"); |
7b4ac7e1 |
398 | |
3bf57d21 |
399 | addbutton (parent, "redisplay", redisplay_button, NULL); |
7b4ac7e1 |
400 | } |
401 | \f |
402 | /* Create a "label window" that just displays the string LABEL. */ |
403 | |
404 | static Widget |
405 | create_label (name, label) |
406 | char *name, *label; |
407 | { |
e91b87a3 |
408 | static Arg labelArgs[2]; |
7b4ac7e1 |
409 | |
410 | XtSetArg (labelArgs[0], XtNname, name); |
3bf57d21 |
411 | |
e91b87a3 |
412 | XtSetArg (labelArgs[1], XtNlabel, label); |
413 | return XtCreateManagedWidget ("label", labelWidgetClass, containing_widget, |
414 | labelArgs, XtNumber (labelArgs)); |
7b4ac7e1 |
415 | } |
416 | |
417 | /* Create a subwindow of PARENT that displays and scrolls the contents |
418 | of file FILENAME. */ |
419 | |
420 | static Widget |
421 | create_text_widget (parent, filename) |
3bf57d21 |
422 | Widget parent; |
7b4ac7e1 |
423 | char *filename; |
424 | { |
3bf57d21 |
425 | static Arg fileArgs[3]; |
426 | XtTextSource src; |
427 | XtTextSink sink; |
4187119d |
428 | Widget text_widget; |
429 | |
430 | text_widget = XtCreateManagedWidget ("disk", textWidgetClass, |
431 | parent, NULL, 0); |
3bf57d21 |
432 | |
7b4ac7e1 |
433 | XtSetArg (fileArgs[0], XtNfile, filename); |
3bf57d21 |
434 | src = XtDiskSourceCreate(parent, fileArgs, 1); |
435 | sink = XtAsciiSinkCreate(parent, NULL, 0); |
e91b87a3 |
436 | |
3bf57d21 |
437 | XtSetArg (fileArgs[0], XtNtextOptions, scrollVertical); |
438 | XtSetArg (fileArgs[1], XtNtextSource, src); |
439 | XtSetArg (fileArgs[2], XtNtextSink, sink); |
4187119d |
440 | XtSetValues (text_widget, fileArgs, XtNumber (fileArgs)); |
441 | return text_widget; |
7b4ac7e1 |
442 | } |
443 | \f |
3bf57d21 |
444 | /* Entry point to create the widgets representing our display. */ |
e91b87a3 |
445 | |
7b4ac7e1 |
446 | int |
447 | xgdb_create_window () |
448 | { |
e91b87a3 |
449 | static Arg frameArgs[]= { |
450 | {XtNwidth, (XtArgVal) 600}, |
451 | {XtNheight, (XtArgVal) 700}, |
452 | }; |
3bf57d21 |
453 | { |
e91b87a3 |
454 | char *dummy1[2]; |
455 | int dummy2 = 1; |
456 | |
457 | dummy1[0] = "xgdb"; |
458 | dummy1[1] = NULL; |
459 | main_widget = XtInitialize ("xgdb", "XGdb", 0, 0, &dummy2, dummy1); |
3bf57d21 |
460 | } |
7b4ac7e1 |
461 | |
e91b87a3 |
462 | screen_display = XtDisplay(main_widget); |
463 | |
464 | /* Create the containing_widget. */ |
465 | |
466 | containing_widget = XtCreateManagedWidget ("frame", vPanedWidgetClass, main_widget, |
467 | frameArgs, XtNumber (frameArgs)); |
468 | /* Create source file name window and add to containing_widget */ |
469 | source_name_widget |
470 | = create_label ("Source File", "No source file yet."); |
471 | |
3bf57d21 |
472 | /* Create exec file name window and add */ |
e91b87a3 |
473 | exec_name_widget = create_label ("Executable", "No executable specified."); |
3bf57d21 |
474 | |
475 | /* Create window full of buttons. */ |
e91b87a3 |
476 | button_box_widget = XtCreateManagedWidget ("buttonbox", boxWidgetClass, |
477 | containing_widget, NULL, 0); |
3bf57d21 |
478 | create_buttons (button_box_widget); |
7b4ac7e1 |
479 | |
7b4ac7e1 |
480 | /* Create an empty source-display window and add to containing_widget */ |
481 | source_text_widget = create_text_widget (containing_widget, "/dev/null"); |
482 | |
e91b87a3 |
483 | XSync(screen_display, 0); |
484 | XtRealizeWidget(main_widget); |
485 | |
486 | #if 0 |
487 | default_gc = XCreateGC (screen_display, XtWindow(containing_widget), 0, NULL); |
488 | /* Create icon window. */ |
7b4ac7e1 |
489 | { |
e91b87a3 |
490 | static Arg iconArgs[2]; |
491 | void (*compiler_bug) () = deiconify_button; |
492 | XtSetArg (iconArgs[0], XtNlabel, "(gdb)"); |
493 | XtSetArg (iconArgs[1], XtNfunction, compiler_bug); |
494 | icon_window = XtCreateWidget ("Icon", commandWidgetClass, |
495 | iconArgs, XtNumber (iconArgs)); |
496 | XMoveWindow (screen_display, icon_window, 100, 100); /* HACK */ |
497 | XSetIconWindow (screen_display, containing_widget, icon_window); |
7b4ac7e1 |
498 | } |
7b4ac7e1 |
499 | |
e91b87a3 |
500 | /* Now make the whole thing appear on the display. */ |
501 | { |
502 | Pixmap pm1, pm2; |
503 | XImage image; |
504 | Cursor curse; |
505 | |
506 | image.width = gdb_width; |
507 | image.height = gdb_height; |
508 | image.xoffset = 0; |
509 | image.format = XYBitmap; |
510 | image.byte_order = LSBFirst; |
511 | image.bitmap_unit = 16; |
512 | image.bitmap_bit_order = LSBFirst; |
513 | image.depth = 1; |
514 | image.bytes_per_line = 2; |
515 | image.bits_per_pixel = 1; |
516 | |
517 | pm1 = XCreatePixmap (screen_display, DefaultScreen (screen_display), |
518 | gdb_width, gdb_height, 1); |
519 | pm2 = XCreatePixmap (screen_display, DefaultScreen (screen_display), |
520 | gdb_width, gdb_height, 1); |
521 | |
522 | image.data = (char *) gdb_bits; |
523 | XPutImage (screen_display, pm1, default_gc, &image, 0, 0, 0, 0, |
524 | gdb_width, gdb_height); |
525 | |
526 | image.data = (char *) gdb_mask_bits; |
527 | XPutImage (screen_display, pm2, default_gc, &image, 0, 0, 0, 0, |
528 | gdb_width, gdb_height); |
529 | |
530 | curse = XCreatePixmapCursor (screen_display, pm1, pm2, |
531 | BlackPixel (screen_display, |
532 | DefaultScreen (screen_display)), |
533 | WhitePixel (screen_display, |
534 | DefaultScreen (screen_display)), |
535 | gdb_x_hot, gdb_y_hot); |
536 | |
537 | XFreePixmap (screen_display, pm1); |
538 | XFreePixmap (screen_display, pm2); |
539 | |
540 | XDefineCursor (screen_display, containing_widget, curse); |
541 | XDefineCursor (screen_display, icon_window, curse); |
542 | } |
543 | #endif 0 |
7b4ac7e1 |
544 | |
7b4ac7e1 |
545 | XFlush (screen_display); |
e91b87a3 |
546 | |
7b4ac7e1 |
547 | return 1; |
548 | } |
549 | \f |
550 | /* xgdb_dispatch -- Loop, dispatching on window events, |
551 | until data is available on FP (which is normally stdin). |
552 | Then return, so the data on FP can be processed. */ |
553 | |
554 | void |
555 | xgdb_dispatch (fp) |
556 | FILE *fp; |
557 | { |
558 | int inmask = 1 << fileno (fp); |
559 | int xmask = 1 << ConnectionNumber (screen_display); |
560 | int rfds = 0; |
561 | int nfds; |
562 | XEvent ev; |
563 | int pend; |
e91b87a3 |
564 | |
7b4ac7e1 |
565 | while (! (rfds & inmask)) |
566 | { |
3bf57d21 |
567 | pend = XPending (screen_display); |
7b4ac7e1 |
568 | if (!pend) |
569 | { |
e91b87a3 |
570 | rfds = inmask | xmask; |
7b4ac7e1 |
571 | /* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */ |
572 | nfds = select (32, &rfds, 0, 0, (struct timeval *) 0); |
573 | } |
574 | if (pend || rfds & xmask) |
575 | { |
576 | XNextEvent (screen_display, &ev); |
577 | XtDispatchEvent (&ev); |
578 | } |
579 | } |
580 | } |
581 | \f |
582 | /* If we use an X window, the GDB command loop is told to call this function |
e91b87a3 |
583 | |
7b4ac7e1 |
584 | before reading a command from stdin. |
585 | PROMPT is saved for later use so buttons can print a prompt-string. */ |
586 | |
587 | void |
588 | xgdb_window_hook (infile, prompt) |
589 | FILE *infile; |
590 | char *prompt; |
591 | { |
592 | prompt_string = prompt; |
593 | xgdb_display_source (); |
594 | xgdb_dispatch (infile); |
595 | } |
596 | |
e91b87a3 |
597 | _initialize_xgdb () |
7b4ac7e1 |
598 | { |
599 | extern void (*window_hook) (); |
600 | extern int inhibit_windows; |
601 | |
602 | if (getenv ("DISPLAY") && ! inhibit_windows) |
4187119d |
603 | { |
604 | if (xgdb_create_window ()) |
605 | window_hook = xgdb_window_hook; |
7b4ac7e1 |
606 | |
4187119d |
607 | specify_exec_file_hook (xgdb_display_exec_file); |
608 | } |
7b4ac7e1 |
609 | } |
610 | |
3bf57d21 |
611 | |