source: vendor/emx/current/src/pmgdb/command.cc

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 42.0 KB
Line 
1/* command.cc
2 Copyright (c) 1996, 1998 Eberhard Mattes
3
4This file is part of pmgdb.
5
6pmgdb is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11pmgdb is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with pmgdb; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21
22#define INCL_DOS
23#define INCL_DOSERRORS
24#define INCL_WIN
25#include <os2.h>
26#include <stdlib.h>
27#include <stdarg.h>
28#include <string.h>
29#include <process.h>
30#include <signal.h>
31#include <io.h>
32#include <fcntl.h>
33#include "string.h"
34#include "pmapp.h"
35#include "pmframe.h"
36#include "pmtxt.h"
37#include "pmtty.h"
38#include "pmgdb.h"
39#include "help.h"
40#include "breakpoi.h"
41#include "display.h"
42#include "threads.h"
43#include "register.h"
44#include "source.h"
45#include "srcfiles.h"
46#include "annotati.h"
47#include "capture.h"
48#include "gdbio.h"
49#include "pmdebug.h"
50#include "command.h"
51
52static HWND hwndFatal;
53
54struct command_window::new_source
55{
56 char *short_filename;
57 char *long_filename;
58 int lineno;
59 bool set_focus;
60};
61
62struct command_window::cmd_hist
63{
64 struct cmd_hist *next;
65 struct cmd_hist *prev;
66 fstring cmd;
67};
68
69void command_window_thread (void *arg)
70{
71 ((struct command_window *)arg)->thread ();
72}
73
74
75// Note: This signal handler is called in thread 1, which has a
76// PM message queue.
77
78static void sigchld_handler (int)
79{
80 // TODO: Offer to save settings
81 // TODO: WinMessageBox has a message loop and can therefore cause
82 // a reentrancy problem
83 WinMessageBox (HWND_DESKTOP, HWND_DESKTOP, (PSZ)"GDB terminated.",
84 (PSZ)"pmgdb", 0,
85 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
86 // TODO: Get and return GDB's termination code
87 exit (0);
88}
89
90
91command_window::command_window (pmapp *in_app, unsigned in_id,
92 const char *fontnamesize, char **in_argv)
93 : pmtty (in_app, in_id, FCF_TASKLIST, NULL, fontnamesize)
94{
95 SWP swp_cmd, swp_dsp, swp_thr, swp_srcs;
96
97 hwndFatal = get_hwndClient ();
98 _fmutex_checked_create (&mutex, 0);
99
100 swp_srcs.cx = in_app->get_screen_width () / 4;
101 swp_srcs.cy = in_app->get_screen_height () / 4;
102 swp_srcs.x = in_app->get_screen_width () - swp_srcs.cx;
103 swp_srcs.y = in_app->get_screen_height () - swp_srcs.cy;
104
105 swp_cmd.cx = swp_srcs.x;
106 swp_cmd.cy = swp_srcs.cy;
107 swp_cmd.x = 0;
108 swp_cmd.y = swp_srcs.y;
109 WinSetWindowPos (get_hwndFrame (), HWND_DESKTOP, swp_cmd.x, swp_cmd.y,
110 swp_cmd.cx, swp_cmd.cy, SWP_SIZE | SWP_MOVE);
111
112 WinQueryWindowPos (get_hwndFrame (), &swp_cmd);
113 swp_srcs.x = swp_cmd.x + swp_cmd.cx;
114 swp_srcs.cx = in_app->get_screen_width () - swp_srcs.x;
115
116 swp_thr.x = swp_srcs.x;
117 swp_thr.y = swp_srcs.y - swp_srcs.cy;
118 swp_thr.cx = swp_srcs.cx;
119 swp_thr.cy = swp_srcs.cy;
120
121 swp_dsp.x = 0;
122 swp_dsp.y = swp_thr.y;
123 swp_dsp.cx = swp_cmd.cx;
124 swp_dsp.cy = swp_thr.cy;
125
126 help_ok = help_init (HELP_TABLE, "pmgdb Help", "pmgdb.hlp", HELP_CMD_KEYS);
127 if (!help_ok)
128 {
129 WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
130 (PSZ)"pmgdb.hlp not found; please set HELP correctly "
131 "in config.sys.", (PSZ)"pmgdb", 0,
132 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
133 help_disable (this);
134 }
135
136 show (true);
137 src_list = NULL; src_menu_id_used = NULL;
138 src_menu_id_count = 0;
139 history = NULL; cur_cmd = NULL;
140 gdb = new gdbio (this);
141 cursor (true);
142
143 argv = NULL; argv_used = 0; argv_size = 0;
144 arg_add ("gdb.exe");
145 arg_add ("--annotate=2");
146 arg_add ("--args");
147 for (int i = 0; in_argv[i] != NULL; ++i)
148 arg_add (in_argv[i]);
149 arg_add (NULL);
150
151 srcs = new source_files_window (this, ID_SOURCE_FILES_WINDOW, &swp_srcs,
152 fontnamesize);
153 if (!help_ok) help_disable (srcs);
154 thr = new threads_window (this, gdb, ID_THREADS_WINDOW, &swp_thr,
155 fontnamesize);
156 if (!help_ok) help_disable (thr);
157 brk = new breakpoints_window (this, gdb, ID_BREAKPOINTS_WINDOW,
158 fontnamesize);
159 if (!help_ok) help_disable (brk);
160 dsp = new display_window (this, gdb, ID_DISPLAY_WINDOW, &swp_dsp,
161 fontnamesize);
162 if (!help_ok) help_disable (dsp);
163 reg = new register_window (this, ID_REGISTER_WINDOW, NULL, fontnamesize);
164 if (!help_ok) help_disable (reg);
165
166 notify (GSC_RUNNING | GSC_EXEC_FILE);
167
168 gdb->send_init ();
169 gdb->queue_cmd ("server set height 0");
170
171 struct sigaction sa;
172 sa.sa_handler = sigchld_handler;
173 sa.sa_flags = 0;
174 sigemptyset (&sa.sa_mask);
175 sigaction (SIGCHLD, &sa, NULL);
176
177 if (_beginthread (command_window_thread, NULL, 0x8000, (void *)this) == -1)
178 abort ();
179}
180
181
182command_window::~command_window ()
183{
184 // TODO: delete cmd_head...
185 pmdbg.exit ();
186 delete brk;
187 delete dsp;
188 delete thr;
189 delete srcs;
190 delete reg;
191 src_node *s, *snext;
192 for (s = src_list; s != NULL; s = snext)
193 {
194 snext = s->next;
195 delete s->src;
196 delete s;
197 }
198 delete[] src_menu_id_used;
199 arg_delete_all ();
200 cmd_hist *h, *hprev;
201 for (h = history; h != NULL; h = hprev)
202 {
203 hprev = h->prev;
204 delete h;
205 }
206
207 // TODO: mutex
208}
209
210
211void command_window::arg_delete_all ()
212{
213 for (int i = 0; argv[i] != NULL; ++i)
214 delete[] argv[i];
215 delete[] argv;
216 argv = NULL; argv_used = 0; argv_size = 0;
217}
218
219
220void command_window::arg_add (const char *str)
221{
222 if (argv_used >= argv_size)
223 {
224 int new_size = argv_size + 16;
225 char **new_argv = new char *[new_size];
226 for (int i = 0; i < argv_size; ++i)
227 new_argv[i] = argv[i];
228 for (int i = argv_size; i < new_size; ++i)
229 new_argv[i] = NULL;
230 delete[] argv;
231 argv = new_argv; argv_size = new_size;
232 }
233
234 char *p;
235 if (str == NULL)
236 p = NULL;
237 else
238 {
239 p = new char[strlen (str) + 1];
240 strcpy (p, str);
241 }
242 argv[argv_used++] = p;
243}
244
245
246void command_window::lock ()
247{
248 _fmutex_checked_request (&mutex, _FMR_IGNINT);
249}
250
251
252void command_window::unlock ()
253{
254 _fmutex_checked_release (&mutex);
255}
256
257
258void command_window::capture_error (const capture *p)
259{
260 WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
261 (PSZ)p->error.get (), (PSZ)"pmgdb", 0,
262 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
263}
264
265
266void command_window::get_breakpoints ()
267{
268 breakpoint_list old;
269 old.steal (breakpoints);
270 capture *capt = gdb->capture_cmd ("server info breakpoints");
271 if (capt != NULL)
272 {
273 for (capture *p = capt->next; p != NULL; p = p->next)
274 {
275 breakpoint bpt;
276 if (bpt.set_from_capture (*p))
277 breakpoints.add (bpt);
278 }
279 gdb->breakpoints_invalid = false;
280 delete_capture (capt);
281 }
282
283 breakpoints.update (old, this, &brkpt_update);
284
285 // OLD goes out of scope here; that will call delete_all()
286}
287
288
289// Callback function for breakpoint_list::update()
290
291void command_window::brkpt_update (int index, const breakpoint *old_bpt,
292 const breakpoint *new_bpt)
293{
294 if (new_bpt == NULL)
295 {
296 // Deletion
297 if (old_bpt->get_source () != NULL)
298 {
299 source_window *src = find_source_short (old_bpt->get_source ());
300 if (src != NULL)
301 src->set_breakpoint (old_bpt->get_lineno (), false, true);
302 }
303 }
304 else if (old_bpt == NULL)
305 {
306 // Insertion
307 if (new_bpt->get_source () != NULL)
308 {
309 source_window *src = find_source_short (new_bpt->get_source ());
310 if (src != NULL)
311 src->set_breakpoint (new_bpt->get_lineno (), true, true);
312 }
313 }
314 else
315 {
316 // Possible update
317 if (old_bpt->get_address () != new_bpt->get_address ())
318 {
319 if (old_bpt->get_source () != NULL)
320 {
321 source_window *src = find_source_short (old_bpt->get_source ());
322 if (src != NULL)
323 src->set_breakpoint (old_bpt->get_lineno (), false, true);
324 }
325 if (new_bpt->get_source () != NULL)
326 {
327 source_window *src = find_source_short (new_bpt->get_source ());
328 if (src != NULL)
329 src->set_breakpoint (new_bpt->get_lineno (), true, true);
330 }
331 }
332 }
333 if (brk != NULL)
334 brk->update (index, old_bpt, new_bpt);
335}
336
337
338void command_window::get_breakpoints (source_window *src, bool paint)
339{
340 const char *name = src->get_short_filename ();
341 // TODO: iterator
342 for (breakpoint_list::brkpt_node *p = breakpoints.list; p != NULL;
343 p = p->next)
344 if (p->get_source () != NULL
345 && _fncmp ((const unsigned char *)p->get_source (),
346 (const unsigned char *)name) == 0)
347 src->set_breakpoint (p->get_lineno (), true, paint);
348}
349
350
351const breakpoint *command_window::get_breakpoint (int n) const
352{
353 return breakpoints.get (n);
354}
355
356
357source_window *command_window::find_source_short (const char *fname)
358{
359 for (src_node *node = src_list; node != NULL; node = node->next)
360 if (_fncmp ((const unsigned char *)node->src->get_short_filename (),
361 (const unsigned char *)fname) == 0)
362 return node->src;
363 return NULL;
364}
365
366
367source_window *command_window::find_source_long (const char *fname)
368{
369 for (src_node *node = src_list; node != NULL; node = node->next)
370 if (_fncmp ((const unsigned char *)node->src->get_long_filename (),
371 (const unsigned char *)fname) == 0)
372 return node->src;
373 return NULL;
374}
375
376
377// lineno == -1: don't change line if file already loaded;
378// don't select line for new file
379// Deselect current line in any source window if both filenames are NULL
380
381void command_window::show_source (const char *short_fname,
382 const char *long_fname, bool set_focus,
383 int lineno)
384{
385 for (const src_node *node = src_list; node != NULL; node = node->next)
386 node->src->show_line (-1);
387 if (short_fname == NULL && long_fname == NULL)
388 return;
389
390 source_window *src = NULL;
391 if (long_fname != NULL)
392 src = find_source_long (long_fname);
393 if (src == NULL && short_fname != NULL)
394 src = find_source_short (short_fname);
395
396 if (src != NULL)
397 {
398 if (lineno != -1)
399 src->show_line (lineno);
400 if (set_focus)
401 src->focus ();
402 }
403 else
404 {
405 new_source ns;
406 ns.short_filename = NULL; ns.long_filename = NULL;
407 if (short_fname != NULL)
408 {
409 // TODO: Use fstring?
410 ns.short_filename = new char [strlen (short_fname) + 1];
411 strcpy (ns.short_filename, short_fname);
412 }
413 if (long_fname != NULL)
414 {
415 ns.long_filename = new char [strlen (long_fname) + 1];
416 strcpy (ns.long_filename, long_fname);
417 }
418 ns.lineno = lineno;
419 ns.set_focus = set_focus;
420 if (same_tid ())
421 show_new_source (&ns);
422 else
423 WinSendMsg (get_hwndClient (), UWM_SOURCE, MPFROMP (&ns), 0);
424 }
425}
426
427
428// FILENAME has been allocated with new char[]!
429
430void command_window::show_new_source (const new_source *ns)
431{
432 unsigned menu_id;
433 MENUITEM mi;
434 char *long_filename = ns->long_filename;
435 char *short_filename = ns->short_filename;
436
437 if (long_filename == NULL || access (long_filename, R_OK) != 0)
438 {
439 char *new_filename = NULL;
440
441 capture *capt = gdb->capture_cmd ("server list %s:1,0",
442 (short_filename != NULL
443 ? short_filename : long_filename));
444 if (capt != NULL && !capt->error.is_set ())
445 {
446 delete_capture (capt);
447 capt = gdb->capture_cmd ("server info source");
448 if (capt != NULL && capt->source_location.is_set ())
449 {
450 const char *s = capt->source_location.get ();
451 new_filename = new char [strlen (s) + 1];
452 strcpy (new_filename, s);
453 }
454 }
455 delete_capture (capt);
456 delete[] long_filename;
457 if (new_filename == NULL)
458 {
459 delete[] short_filename;
460 return; // TODO: Message box
461 }
462 long_filename = new_filename;
463 }
464
465 if (short_filename == NULL)
466 {
467 const char *s = _getname (long_filename);
468 short_filename = new char[strlen (s)];
469 strcpy (short_filename, s);
470 }
471 char *p = (char *)memchr (src_menu_id_used, 0, src_menu_id_count);
472 if (p != NULL)
473 menu_id = p - src_menu_id_used;
474 else
475 {
476 int new_count = src_menu_id_count + 32;
477 p = new char[new_count];
478 memcpy (p, src_menu_id_used, src_menu_id_count);
479 memset (p + src_menu_id_count, 0, new_count - src_menu_id_count);
480 delete[] src_menu_id_used;
481 src_menu_id_used = p;
482 menu_id = src_menu_id_count;
483 src_menu_id_count = new_count;
484 }
485 src_menu_id_used[menu_id] = 1;
486 menu_id += IDM_WIN_SRC;
487
488 src_node *new_node = new src_node;
489 new_node->next = NULL;
490 new_node->src = new source_window (get_app (), ID_SOURCE_WINDOW, NULL,
491 short_filename, long_filename, this, gdb);
492 if (!help_ok) help_disable (new_node->src);
493 new_node->menu_id = menu_id;
494 new_node->hwndWinMenu = new_node->src->get_hwndMenu_from_id (IDM_WINMENU);
495
496 mi.iPosition = MIT_END;
497 mi.afStyle = MIS_TEXT;
498 mi.afAttribute = 0;
499 mi.hwndSubMenu = NULLHANDLE;
500 mi.hItem = 0;
501 mi.id = new_node->menu_id;
502 const char *new_name = short_filename;
503
504 WinSendMsg (get_hwndMenu_from_id (IDM_WINMENU),
505 MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
506 WinSendMsg (thr->get_hwndMenu_from_id (IDM_WINMENU),
507 MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
508 WinSendMsg (brk->get_hwndMenu_from_id (IDM_WINMENU),
509 MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
510 WinSendMsg (dsp->get_hwndMenu_from_id (IDM_WINMENU),
511 MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
512 WinSendMsg (srcs->get_hwndMenu_from_id (IDM_WINMENU),
513 MM_INSERTITEM, MPFROMP (&mi), MPFROMP (new_name));
514
515 for (src_node *pn = src_list; pn != NULL; pn = pn->next)
516 {
517 mi.id = new_node->menu_id;
518 WinSendMsg (pn->hwndWinMenu, MM_INSERTITEM, MPFROMP (&mi),
519 MPFROMP (new_name));
520 mi.id = pn->menu_id;
521 WinSendMsg (new_node->hwndWinMenu, MM_INSERTITEM, MPFROMP (&mi),
522 MPFROMP (pn->src->get_short_filename ()));
523 }
524 src_node **patch = &src_list;
525 while (*patch != NULL)
526 patch = &(*patch)->next;
527 *patch = new_node;
528
529 if (ns->lineno != -1)
530 new_node->src->show_line (ns->lineno);
531 if (ns->set_focus)
532 new_node->src->focus ();
533
534 delete[] short_filename;
535 delete[] long_filename;
536}
537
538
539void command_window::delete_source (source_window *src)
540{
541 // TODO: Use Mutex to prevent another thread from accessing src_list and SRC
542 src_node **patch = &src_list;
543 while (*patch != NULL && (*patch)->src != src)
544 patch = &(*patch)->next;
545 if (*patch != NULL)
546 {
547 src_node *p = *patch;
548 *patch = p->next;
549 src_menu_id_used[p->menu_id] = 0;
550 for (src_node *pn = src_list; pn != NULL; pn = pn->next)
551 WinSendMsg (pn->src->get_hwndMenu (), MM_DELETEITEM,
552 MPFROM2SHORT (p->menu_id, TRUE), 0);
553 WinSendMsg (get_hwndMenu (), MM_DELETEITEM,
554 MPFROM2SHORT (p->menu_id, TRUE), 0);
555 WinSendMsg (thr->get_hwndMenu (), MM_DELETEITEM,
556 MPFROM2SHORT (p->menu_id, TRUE), 0);
557 WinSendMsg (brk->get_hwndMenu (), MM_DELETEITEM,
558 MPFROM2SHORT (p->menu_id, TRUE), 0);
559 WinSendMsg (dsp->get_hwndMenu (), MM_DELETEITEM,
560 MPFROM2SHORT (p->menu_id, TRUE), 0);
561 WinSendMsg (srcs->get_hwndMenu (), MM_DELETEITEM,
562 MPFROM2SHORT (p->menu_id, TRUE), 0);
563 delete p;
564 }
565 delete src;
566}
567
568
569bool command_window::open_dialog (char *buf, const char *title,
570 const char *fname)
571{
572 FILEDLG fdlg;
573
574 memset (&fdlg, 0, sizeof (fdlg));
575 fdlg.cbSize = sizeof (fdlg);
576 fdlg.fl = FDS_OPEN_DIALOG | FDS_CENTER;
577 fdlg.ulUser = 0;
578 fdlg.lReturn = 0;
579 fdlg.pszTitle = (PSZ)title;
580 fdlg.pszOKButton = (PSZ)"Open";
581 fdlg.pfnDlgProc = NULL;
582 fdlg.pszIType = NULL;
583 fdlg.papszITypeList = NULL;
584 fdlg.pszIDrive = NULL;
585 fdlg.papszIDriveList = NULL;
586 fdlg.hMod = NULLHANDLE;
587 strcpy (fdlg.szFullFile, fname);
588 fdlg.papszFQFilename = NULL;
589 fdlg.ulFQFCount = 0;
590 fdlg.usDlgId = 0;
591 fdlg.x = 0; fdlg.y = 0;
592 fdlg.sEAType = 0;
593 return (WinFileDlg (HWND_DESKTOP, get_hwndClient (), &fdlg)
594 && fdlg.lReturn == DID_OK
595 && _abspath (buf, fdlg.szFullFile, CCHMAXPATH) == 0);
596}
597
598
599void command_window::open_exec ()
600{
601 char aname[CCHMAXPATH];
602 if (open_dialog (aname, "Open program file", "*.exe"))
603 gdb->send_cmd ("server file %s", aname);
604}
605
606
607void command_window::open_core ()
608{
609 char aname[CCHMAXPATH];
610 if (open_dialog (aname, "Open core file", "*"))
611 gdb->send_cmd ("server core-file %s", aname);
612}
613
614
615void command_window::open_source ()
616{
617 char aname[CCHMAXPATH];
618 if (open_dialog (aname, "Open source file", "*"))
619 show_source (NULL, aname, true, -1);
620}
621
622
623void command_window::kill_input ()
624{
625 backspace (input_line.length ());
626 input_line.set (0);
627}
628
629
630void command_window::replace_command (const char *s)
631{
632 kill_input ();
633 input_line.set (s);
634 puts (s);
635}
636
637
638void command_window::exec_command ()
639{
640 if (input_line.length () != 0)
641 {
642 cmd_hist *p = new cmd_hist;
643 p->cmd = input_line;
644 p->prev = history;
645 p->next = NULL;
646 if (history != NULL)
647 history->next = p;
648 history = p;
649 }
650 cur_cmd = NULL;
651
652 input_line.append ("\n", 1);
653 puts ("\n", 1);
654 gdb->send_str ((const char *)input_line, input_line.length ());
655 input_line.set (0);
656}
657
658
659void command_window::from_history (bool next)
660{
661 if (cur_cmd == NULL)
662 {
663 if (history == NULL || next)
664 {
665 WinAlarm (HWND_DESKTOP, WA_ERROR);
666 return;
667 }
668 cur_cmd = history;
669 }
670 else
671 {
672 cmd_hist *p = next ? cur_cmd->next : cur_cmd->prev;
673 if (p == NULL)
674 {
675 WinAlarm (HWND_DESKTOP, WA_ERROR);
676 return;
677 }
678 cur_cmd = p;
679 }
680 replace_command (cur_cmd->cmd);
681}
682
683
684void command_window::key (char c)
685{
686 if (gdb->gdb_prompt != gdbio::GSP_CMD && gdb->gdb_prompt != gdbio::GSP_OTHER)
687 {
688 WinAlarm (HWND_DESKTOP, WA_ERROR);
689 return;
690 }
691 if (c == 8 && input_line.length () > 0)
692 {
693 backspace ();
694 input_line.set (input_line.length () - 1);
695 }
696 else if (c == '\n' || c == '\r')
697 {
698 exec_command ();
699 }
700 else if ((unsigned char)c >= 0x20)
701 {
702 input_line.append (&c, 1);
703 puts ((char *)&c, 1);
704 }
705}
706
707
708HWND command_window::create_hwnd_menu ()
709{
710 return WinCreateWindow (get_hwndClient (), WC_MENU, (PSZ)"",
711 0, 0, 0, 0, 0,
712 get_hwndClient (), HWND_TOP, 0,
713 NULL, NULL);
714}
715
716
717#define MAX_MENU 26
718
719void command_window::completion_menu (HWND hwnd, int start, int count,
720 int skip)
721{
722 MENUITEM mi;
723 if (count < MAX_MENU)
724 {
725 mi.iPosition = MIT_END;
726 mi.afStyle = MIS_TEXT;
727 mi.afAttribute = 0;
728 mi.hwndSubMenu = NULLHANDLE;
729 mi.hItem = 0;
730 for (int i = 0; i < count; ++i)
731 {
732 mi.id = IDM_COMPLETIONS + start + i;
733 WinSendMsg (hwnd, MM_INSERTITEM, MPFROMP (&mi),
734 MPFROMP (completions[start + i] + skip));
735 }
736 }
737 else
738 {
739 int i, j, nsub = 1;
740 for (i = 1; i < count; ++i)
741 if (completions[start+i][skip] != completions[start+i-1][skip])
742 ++nsub;
743 bool initial_char = nsub >= 2 && nsub < MAX_MENU;
744 int number = 1;
745 mi.iPosition = MIT_END;
746 mi.afStyle = MIS_SUBMENU | MIS_TEXT;
747 mi.afAttribute = 0;
748 mi.hItem = 0;
749 mi.id = 0;
750 int subcount, max_subcount = (count + MAX_MENU - 1) / MAX_MENU;
751 char text[20];
752 for (i = 0; i < count; i += subcount)
753 {
754 if (initial_char)
755 {
756 text[0] = completions[start+i][skip];
757 text[1] = 0;
758 for (j = i + 1; j < count; ++j)
759 if (completions[start+j][skip] != completions[start+i][skip])
760 break;
761 subcount = j - i;
762 }
763 else
764 {
765 _itoa (number++, text, 10);
766 subcount = count - i;
767 if (subcount > max_subcount) subcount = max_subcount;
768 }
769 mi.hwndSubMenu = create_hwnd_menu ();
770 completion_menu (mi.hwndSubMenu, start + i, subcount, skip);
771 WinSendMsg (hwnd, MM_INSERTITEM, MPFROMP (&mi), MPFROMP (text));
772 }
773 }
774}
775
776
777void command_window::complete ()
778{
779 if (gdb->gdb_prompt != gdbio::GSP_CMD && gdb->gdb_prompt != gdbio::GSP_OTHER)
780 {
781 WinAlarm (HWND_DESKTOP, WA_ERROR);
782 return;
783 }
784 // TODO: Don't do this in the PM thread (time!)
785 // TODO: hourglass
786 capture *capt = gdb->capture_cmd ("server complete %s",
787 (const char *)input_line);
788 if (capt == NULL)
789 {
790 WinAlarm (HWND_DESKTOP, WA_ERROR);
791 return;
792 }
793 delete_capture (capt);
794 completions = gdb->get_output ();
795 POINTL ptl;
796 if (completions.get_lines () == 1)
797 complete (completions[0]);
798 else if (completions.get_lines () != 0 && get_xy (&ptl))
799 {
800 completions.sort ();
801 int skip = 0;
802 char *blank = strrchr (input_line, ' ');
803 if (blank != NULL)
804 skip = blank + 1 - (const char *)input_line;
805
806 HWND hwndPopup = create_hwnd_menu ();
807 completion_menu (hwndPopup, 0, completions.get_lines (), skip);
808 WinPopupMenu (get_hwndFrame (), get_hwndClient (),
809 hwndPopup, ptl.x, ptl.y, 0,
810 (PU_HCONSTRAIN | PU_VCONSTRAIN | PU_NONE
811 | PU_KEYBOARD | PU_MOUSEBUTTON1));
812 }
813}
814
815
816void command_window::complete (const char *p)
817{
818 if (p != NULL && strncmp (p, input_line, input_line.length ()) == 0)
819 {
820 p += input_line.length ();
821 size_t len = strlen (p);
822 input_line.append (p, len);
823 puts (p, len);
824 }
825}
826
827
828void command_window::font ()
829{
830 if (font_dialog ())
831 {
832 srcs->set_font (*this);
833 thr->set_font (*this);
834 brk->set_font (*this);
835 dsp->set_font (*this);
836 reg->set_font (*this);
837 for (src_node *pn = src_list; pn != NULL; pn = pn->next)
838 pn->src->set_font (*this);
839 }
840}
841
842
843MRESULT command_window::wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
844{
845 unsigned fsflags = SHORT1FROMMP (mp1);
846 unsigned usch = SHORT1FROMMP (mp2);
847 unsigned usvk = SHORT2FROMMP (mp2);
848 if (fsflags & KC_KEYUP)
849 return 0;
850 if (fsflags & KC_VIRTUALKEY)
851 {
852 HWND hwndTarget = NULLHANDLE;
853 switch (usvk)
854 {
855 case VK_UP:
856 from_history (false);
857 return 0;
858 case VK_DOWN:
859 from_history (true);
860 return 0;
861 case VK_PAGEUP:
862 case VK_PAGEDOWN:
863 if (SHORT1FROMMP (mp1) & KC_CTRL)
864 hwndTarget = get_hwndHbar ();
865 else
866 hwndTarget = get_hwndVbar ();
867 break;
868 }
869 if (hwndTarget != NULLHANDLE)
870 {
871 if (WinIsWindowEnabled (hwndTarget))
872 WinPostMsg (hwndTarget, msg, mp1, mp2);
873 return 0;
874 }
875 }
876 if (fsflags & KC_CHAR)
877 {
878 key (usch);
879 return 0;
880 }
881 if ((fsflags & (KC_CTRL|KC_VIRTUALKEY)) == KC_CTRL
882 && usch >= 0x40 && usch <= 0x7f)
883 {
884 key (usch & 0x1f);
885 return 0;
886 }
887 return WinDefWindowProc (hwnd, msg, mp1, mp2);
888}
889
890
891MRESULT command_window::pmdebugmode_msg (HWND hwnd, ULONG msg,
892 MPARAM mp1, MPARAM mp2)
893{
894 MRESULT mr;
895
896 switch (msg)
897 {
898 case WM_INITDLG:
899 dlg_sys_menu (hwnd);
900 WinSetWindowPtr (hwnd, QWL_USER, this);
901 WinSendDlgItemMsg (hwnd, IDC_SYNC, BM_SETCHECK,
902 MPFROMSHORT (pmdbg.get_mode () == pmdebug::sync), 0);
903 break;
904
905 case WM_COMMAND:
906 switch (SHORT1FROMMP (mp1))
907 {
908 case DID_OK:
909 mr = WinSendDlgItemMsg (hwnd, IDC_SYNC, BM_QUERYCHECK, 0, 0);
910 pmdbg.set_mode (SHORT1FROMMR (mr) ? pmdebug::sync : pmdebug::off,
911 get_hwndClient ());
912 WinDismissDlg (hwnd, 0);
913 return 0;
914 }
915 break;
916 }
917 return WinDefDlgProc (hwnd, msg, mp1, mp2);
918}
919
920
921MRESULT EXPENTRY dlg_pmdebugmode (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
922{
923 command_window *p;
924
925 if (msg == WM_INITDLG)
926 p = (command_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
927 else
928 p = (command_window *)WinQueryWindowPtr (hwnd, QWL_USER);
929 return p->pmdebugmode_msg (hwnd, msg, mp1, mp2);
930}
931
932
933MRESULT command_window::startup_msg (HWND hwnd, ULONG msg,
934 MPARAM mp1, MPARAM mp2)
935{
936 MRESULT mr;
937 char *s, buf[512];
938
939 switch (msg)
940 {
941 case WM_INITDLG:
942 dlg_sys_menu (hwnd);
943 WinSetWindowPtr (hwnd, QWL_USER, this);
944 WinSendDlgItemMsg (hwnd, IDC_CLOSE_WIN, BM_SETCHECK,
945 MPFROMSHORT (gdb->get_setshow_boolean ("close")), 0);
946
947 WinSendDlgItemMsg (hwnd, IDC_ARGS, EM_SETTEXTLIMIT,
948 MPFROMSHORT (128), 0);
949 s = gdb->get_setshow_string ("args");
950 WinSetDlgItemText (hwnd, IDC_ARGS, (PSZ)s);
951 delete[] s;
952 break;
953
954 case WM_COMMAND:
955 switch (SHORT1FROMMP (mp1))
956 {
957 case DID_OK:
958 case IDC_RUN:
959 mr = WinSendDlgItemMsg (hwnd, IDC_CLOSE_WIN, BM_QUERYCHECK, 0, 0);
960 // TODO: Only if changed (handle in caller, using a structure)
961 gdb->set_setshow_boolean ("close", (bool)SHORT1FROMMR (mr));
962
963 WinQueryDlgItemText (hwnd, IDC_ARGS, sizeof (buf), (PSZ)buf);
964 gdb->set_setshow_string ("args", buf);
965 WinDismissDlg (hwnd, SHORT1FROMMP (mp1));
966 return 0;
967 }
968 break;
969 }
970 return WinDefDlgProc (hwnd, msg, mp1, mp2);
971}
972
973
974MRESULT EXPENTRY dlg_startup (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
975{
976 command_window *p;
977
978 if (msg == WM_INITDLG)
979 p = (command_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
980 else
981 p = (command_window *)WinQueryWindowPtr (hwnd, QWL_USER);
982 return p->startup_msg (hwnd, msg, mp1, mp2);
983}
984
985
986MRESULT EXPENTRY dlg_about (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
987{
988 switch (msg)
989 {
990 case WM_INITDLG:
991 dlg_sys_menu (hwnd);
992 break;
993 case WM_COMMAND:
994 switch (SHORT1FROMMP (mp1))
995 {
996 case DID_OK:
997 WinDismissDlg (hwnd, TRUE);
998 return 0;
999 }
1000 break;
1001 }
1002 return WinDefDlgProc (hwnd, msg, mp1, mp2);
1003}
1004
1005
1006MRESULT command_window::history_msg (HWND hwnd, ULONG msg,
1007 MPARAM mp1, MPARAM mp2)
1008{
1009 switch (msg)
1010 {
1011 case WM_INITDLG:
1012 dlg_sys_menu (hwnd);
1013 WinSetWindowPtr (hwnd, QWL_USER, this);
1014 WinSetDlgItemText (hwnd, IDC_LIST, input_line);
1015 for (cmd_hist *p = history; p != NULL; p = p->prev)
1016 WinSendDlgItemMsg (hwnd, IDC_LIST, LM_INSERTITEM,
1017 MPFROMSHORT (LIT_END),
1018 MPFROMP ((const char *)p->cmd));
1019 break;
1020
1021 case WM_COMMAND:
1022 switch (SHORT1FROMMP (mp1))
1023 {
1024 case DID_OK:
1025 int len = WinQueryDlgItemTextLength (hwnd, IDC_LIST);
1026 char *text = (char *)alloca (len + 1);
1027 *text = 0;
1028 if (WinQueryDlgItemText (hwnd, IDC_LIST, len + 1, (PSZ)text) != 0)
1029 {
1030 replace_command (text);
1031 exec_command ();
1032 }
1033 WinDismissDlg (hwnd, 0);
1034 return 0;
1035 }
1036 break;
1037 }
1038 return WinDefDlgProc (hwnd, msg, mp1, mp2);
1039}
1040
1041
1042MRESULT EXPENTRY dlg_history (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1043{
1044 command_window *p;
1045
1046 if (msg == WM_INITDLG)
1047 p = (command_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
1048 else
1049 p = (command_window *)WinQueryWindowPtr (hwnd, QWL_USER);
1050 return p->history_msg (hwnd, msg, mp1, mp2);
1051}
1052
1053
1054MRESULT command_window::wm_command (HWND hwnd, ULONG msg,
1055 MPARAM mp1, MPARAM mp2)
1056{
1057 pm_create create;
1058 unsigned id = SHORT1FROMMP (mp1);
1059 switch (id)
1060 {
1061 case IDM_EXIT:
1062 WinPostMsg (get_hwndFrame (), WM_CLOSE, 0, 0);
1063 return 0;
1064
1065 case IDM_OPEN_EXEC:
1066 open_exec ();
1067 return 0;
1068
1069 case IDM_OPEN_CORE:
1070 open_core ();
1071 return 0;
1072
1073 case IDM_OPEN_SOURCE:
1074 open_source ();
1075 return 0;
1076
1077 case IDM_WHERE:
1078 where ();
1079 return 0;
1080
1081 case IDM_COMPLETE:
1082 complete ();
1083 return 0;
1084
1085 case IDM_HISTORY:
1086 create.cb = sizeof (create);
1087 create.ptr = (void *)this;
1088 WinDlgBox (HWND_DESKTOP, hwnd, dlg_history, 0, IDD_HISTORY,
1089 &create);
1090 return 0;
1091
1092 case IDM_FONT:
1093 font ();
1094 return 0;
1095
1096 case IDM_ANNOTATE:
1097 gdb->show_annotations = !gdb->show_annotations;
1098 menu_check (IDM_ANNOTATE, gdb->show_annotations);
1099 return 0;
1100
1101 case IDM_PMDEBUGMODE:
1102 create.cb = sizeof (create);
1103 create.ptr = (void *)this;
1104 WinDlgBox (HWND_DESKTOP, hwnd, dlg_pmdebugmode, 0, IDD_PMDEBUGMODE,
1105 &create);
1106 return 0;
1107
1108 case IDM_STARTUP:
1109 create.cb = sizeof (create);
1110 create.ptr = (void *)this;
1111 if (WinDlgBox (HWND_DESKTOP, hwnd, dlg_startup, 0, IDD_STARTUP,
1112 &create) == IDC_RUN)
1113 {
1114 prepare_run ();
1115 run_command ();
1116 }
1117 return 0;
1118
1119 case IDM_BRKPT_LIST:
1120 brk->show (true);
1121 brk->focus ();
1122 return 0;
1123
1124 case IDM_BRKPT_LINE:
1125 brk->add_line (NULL);
1126 return 0;
1127
1128 case IDM_GO:
1129 prepare_run ();
1130 if (gdb->gdb_running == gdbio::GSR_NONE)
1131 run_command ();
1132 else
1133 gdb->send_cmd ("server continue");
1134 return 0;
1135
1136 case IDM_RESTART:
1137 prepare_run ();
1138 run_command ();
1139 return 0;
1140
1141 case IDM_STEPINTO:
1142 prepare_run ();
1143 gdb->send_cmd ("server step");
1144 return 0;
1145
1146 case IDM_STEPOVER:
1147 prepare_run ();
1148 gdb->send_cmd ("server next");
1149 return 0;
1150
1151 case IDM_ISTEPINTO:
1152 prepare_run ();
1153 gdb->send_cmd ("server stepi");
1154 return 0;
1155
1156 case IDM_ISTEPOVER:
1157 prepare_run ();
1158 gdb->send_cmd ("server nexti");
1159 return 0;
1160
1161 case IDM_FINISH:
1162 prepare_run ();
1163 gdb->send_cmd ("server finish");
1164 return 0;
1165
1166 case IDM_WIN_CMD:
1167 show (true);
1168 focus ();
1169 return 0;
1170
1171 case IDM_WIN_BRK:
1172 brk->show (true);
1173 brk->focus ();
1174 return 0;
1175
1176 case IDM_WIN_THR:
1177 thr->show (true);
1178 thr->focus ();
1179 return 0;
1180
1181 case IDM_WIN_DSP:
1182 dsp->show (true);
1183 dsp->focus ();
1184 return 0;
1185
1186 case IDM_WIN_SRCS:
1187 srcs->show (true);
1188 srcs->focus ();
1189 return 0;
1190
1191 case IDM_WIN_REG:
1192 reg->show (true);
1193 update_registers ();
1194 reg->focus ();
1195 return 0;
1196
1197 case IDM_ABOUT:
1198 WinDlgBox (HWND_DESKTOP, hwnd, dlg_about, 0, IDD_ABOUT, NULL);
1199 return 0;
1200
1201 case IDM_TUTORIAL:
1202 WinSendMsg (get_hwndHelp (), HM_DISPLAY_HELP,
1203 MPFROMSHORT (HELP_TUTORIAL), MPFROMSHORT (HM_RESOURCEID));
1204 return 0;
1205
1206 case IDM_HELP_HELP:
1207 WinSendMsg (get_hwndHelp (), HM_DISPLAY_HELP,
1208 MPFROMSHORT (0), MPFROMSHORT (HM_RESOURCEID));
1209 return 0;
1210
1211 case IDM_HELP_KEYS:
1212 WinSendMsg (get_hwndHelp (), HM_KEYS_HELP, 0, 0);
1213 return 0;
1214
1215 case IDM_HELP_INDEX:
1216 WinSendMsg (get_hwndHelp (), HM_HELP_INDEX, 0, 0);
1217 return 0;
1218
1219 case IDM_HELP_CONTENTS:
1220 WinSendMsg (get_hwndHelp (), HM_HELP_CONTENTS, 0, 0);
1221 return 0;
1222
1223 default:
1224 if (id >= IDM_WIN_SRC && id < IDM_WIN_SRC + (unsigned)src_menu_id_count)
1225 {
1226 src_node *pn = src_list;
1227 while (pn != NULL && pn->menu_id != id)
1228 pn = pn->next;
1229 if (pn != NULL)
1230 {
1231 pn->src->show (true);
1232 pn->src->focus ();
1233 return 0;
1234 }
1235 }
1236 else if (id >= IDM_COMPLETIONS
1237 && id < IDM_COMPLETIONS + (unsigned)completions.get_lines ())
1238 complete (completions[id - IDM_COMPLETIONS]);
1239 break;
1240 }
1241 return WinDefWindowProc (hwnd, msg, mp1, mp2);
1242}
1243
1244
1245MRESULT command_window::wm_activate (HWND hwnd, ULONG msg,
1246 MPARAM mp1, MPARAM mp2)
1247{
1248 if (SHORT1FROMMP (mp1))
1249 associate_help (get_hwndFrame ());
1250 return WinDefWindowProc (hwnd, msg, mp1, mp2);
1251}
1252
1253
1254bool command_window::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1255{
1256 unsigned change;
1257
1258 if (parent::wm_user (hwnd, msg, mp1, mp2))
1259 return true;
1260 switch (msg)
1261 {
1262 case UWM_STATE:
1263 change = LONGFROMMP (mp1);
1264 if (change & GSC_PROMPT)
1265 {
1266 // TODO: Other menus!
1267 menu_enable (IDM_RUNMENU, gdb->is_ready ());
1268 if (gdb->is_ready ())
1269 {
1270 if (gdb->stopped_pending)
1271 {
1272 gdb->stopped_pending = false;
1273 capture *frames = gdb->frame_head;
1274 if (frames != NULL)
1275 {
1276 gdb->frame_head = NULL; gdb->frame_cur = NULL;
1277 if (frames->source_file.is_set ())
1278 show_source (NULL, frames->source_file.get (),
1279 true, frames->source_lineno.get ());
1280 else
1281 show_source (NULL, NULL, false, -1);
1282 delete_capture (frames);
1283 }
1284 else
1285 show_source (NULL, NULL, false, -1);
1286 if (reg->is_visible ())
1287 update_registers ();
1288 }
1289 capture *displays = gdb->display_head;
1290 if (displays != NULL)
1291 {
1292 gdb->display_head = NULL; gdb->display_cur = NULL;
1293 for (capture *p = displays; p != NULL; p = p->next)
1294 dsp->update (p->disp_number.get (), p->disp_expr.get (),
1295 p->disp_format.get (), p->disp_value.get (),
1296 p->disp_enable.get ());
1297 delete_capture (displays);
1298 }
1299 }
1300 }
1301 if (change & GSC_RUNNING)
1302 {
1303 // TODO: IDM_GO
1304 bool running = !gdb->is_nochild ();
1305 menu_enable (IDM_STEPOVER, running);
1306 menu_enable (IDM_STEPINTO, running);
1307 menu_enable (IDM_ISTEPOVER, running);
1308 menu_enable (IDM_ISTEPINTO, running);
1309 menu_enable (IDM_FINISH, running);
1310 }
1311 if (change & GSC_BREAKPOINTS)
1312 {
1313 // TODO: Don't do this in the PM thread (time!)
1314 // TODO: This may break if this message is processed while
1315 // we're operating on breakpoints (Edit->Modify!)
1316 get_breakpoints ();
1317 }
1318 if (change & GSC_EXEC_FILE)
1319 new_debuggee ();
1320 return true;
1321
1322 case UWM_SOURCE:
1323 show_new_source ((const new_source *)PVOIDFROMMP (mp1));
1324 return true;
1325
1326 case UWM_CLOSE_SRC:
1327 delete_source ((source_window *)PVOIDFROMMP (mp1));
1328 return true;
1329
1330 case UWM_PMDBG_START:
1331 pmdbg.start ();
1332 return true;
1333
1334 case UWM_PMDBG_STOP:
1335 pmdbg.stop ();
1336 return true;
1337
1338 case UWM_PMDBG_TERM:
1339 pmdbg.term ();
1340 return true;
1341
1342 case UWM_FATAL:
1343 WinMessageBox (HWND_DESKTOP, HWND_DESKTOP, (PSZ)PVOIDFROMMP (mp1),
1344 (PSZ)"pmgdb", 0,
1345 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
1346 exit (1);
1347
1348 default:
1349 return false;
1350 }
1351}
1352
1353
1354MRESULT command_window::wm_close (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1355{
1356 if (gdb->gdb_running != gdbio::GSR_NONE)
1357 {
1358 LONG response
1359 = WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
1360 (PSZ)"The program is running -- quit anyway?",
1361 (PSZ)get_name (), 0,
1362 (MB_YESNO | MB_QUERY | MB_DEFBUTTON1 | MB_APPLMODAL
1363 | MB_MOVEABLE));
1364 if (response != MBID_YES)
1365 return 0;
1366 }
1367 return parent::wm_close (hwnd, msg, mp1, mp2);
1368}
1369
1370
1371void command_window::thread ()
1372{
1373 int ipipe[2], opipe[2], sin, sout, serr;
1374 int pid, from_gdb;
1375 pmapp app ("pmgdb");
1376 app.no_message_loop ();
1377
1378 if ((sin = dup (0)) == -1) abort ();
1379 if ((sout = dup (1)) == -1) abort ();
1380 if ((serr = dup (2)) == -1) abort ();
1381
1382 if (pipe (ipipe) != 0) abort ();
1383 if (pipe (opipe) != 0) abort ();
1384 if (fcntl (ipipe[0], F_SETFD, 1) != 0) abort ();
1385 if (fcntl (opipe[1], F_SETFD, 1) != 0) abort ();
1386
1387 from_gdb = ipipe[0];
1388 setmode (opipe[1], O_BINARY);
1389 gdb->send_init (opipe[1]);
1390
1391 if (dup2 (opipe[0], 0) != 0) abort ();
1392 if (dup2 (ipipe[1], 1) != 1) abort ();
1393 if (dup2 (ipipe[1], 2) != 2) abort ();
1394
1395 close (ipipe[1]);
1396 close (opipe[0]);
1397
1398 // Get the current priority of this thread.
1399
1400 PPIB ppib;
1401 PTIB ptib;
1402 DosGetInfoBlocks (&ptib, &ppib);
1403 ULONG old_priority = ptib->tib_ptib2->tib2_ulpri;
1404
1405 // Temporarily change the priority of this thread to let GDB inherit
1406 // foreground server priority. Setting the priority of a process in
1407 // another session does not work after starting that session.
1408
1409 if (DosSetPriority (PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0) != 0)
1410 DosBeep (400, 200);
1411
1412 pid = spawnvp (P_SESSION | P_MINIMIZE | P_BACKGROUND, argv[0], argv);
1413
1414 // Restore the priority of this thread. (This won't restore the
1415 // priority of any threads started by spawnvp() -- but that doesn't
1416 // matter because the thread created by emx.dll for
1417 // spawnv(P_SESSION) just waits for termination of our child
1418 // sessions. Having too high a priority for such a thread doesn't
1419 // hurt.)
1420
1421 if (DosSetPriority (PRTYS_THREAD, (old_priority >> 8) & 0xff,
1422 old_priority & 0xff, 0) != 0
1423 || DosSetPriority (PRTYS_THREAD, (old_priority >> 8) & 0xff,
1424 old_priority & 0xff, 0) != 0)
1425 DosBeep (400, 200);
1426
1427 dup2 (sin, 0); close (sin);
1428 dup2 (sout, 1); close (sout);
1429 dup2 (serr, 2); close (serr);
1430
1431 if (pid == -1)
1432 {
1433 WinPostMsg (get_hwndClient (), UWM_FATAL,
1434 MPFROMP ("Cannot run gdb.exe."), 0);
1435 return;
1436 }
1437
1438 gdb->send_init ();
1439 gdb->start (from_gdb);
1440 gdb->parse_gdb ();
1441}
1442
1443
1444void command_window::handle_output (const char *text, int len)
1445{
1446 puts (text, len);
1447}
1448
1449
1450void command_window::show_annotation (const annotation *ann)
1451{
1452 pmtxt_attr a = get_attr ();
1453 set_attr ();
1454 if (ann->get_code () == annotation::UNKNOWN)
1455 set_bg_color (CLR_GREEN);
1456 else
1457 set_fg_color (CLR_DARKGREEN);
1458 if (get_column () + ann->get_text_len () + 2 > 80)
1459 puts ("{}\n", 3);
1460 puts ("{", 1);
1461 puts (ann->get_text (), ann->get_text_len ());
1462 puts ("}", 1);
1463 set_attr (a);
1464}
1465
1466
1467void command_window::exec_file (const char *s, int len)
1468{
1469 lock ();
1470 if (s == NULL)
1471 debuggee.set_null ();
1472 else
1473 debuggee.set (s, len);
1474 unlock ();
1475}
1476
1477
1478void command_window::notify (unsigned change)
1479{
1480 // Use WinPostMsg instead of WinSendMsg because there may not yet be
1481 // a message loop
1482 WinPostMsg (get_hwndClient (), UWM_STATE, MPFROMLONG (change), 0);
1483 for (src_node *p = src_list; p != NULL; p = p->next)
1484 WinPostMsg (p->src->get_hwndClient (), UWM_STATE, MPFROMLONG (change), 0);
1485}
1486
1487
1488void command_window::new_debuggee ()
1489{
1490 srcs->delete_all ();
1491 srcs->sync ();
1492 lock ();
1493 menu_enable (IDM_RESTART, !debuggee.is_null ());
1494 menu_enable (IDM_GO, !debuggee.is_null ());
1495 if (!debuggee.is_null ())
1496 {
1497 ULONG flags;
1498 if (DosQueryAppType (debuggee, &flags) == 0
1499 && (flags & FAPPTYP_EXETYPE) == FAPPTYP_WINDOWAPI)
1500 pmdbg.set_mode (pmdebug::sync, get_hwndClient ());
1501 const char *temp = _getname (debuggee);
1502 unlock ();
1503 astring title; title = "pmgdb - ";
1504 title.append (temp);
1505 set_title (title);
1506 bool ok = false;
1507 capture *capt = gdb->capture_cmd ("server info sources");
1508 if (capt != NULL)
1509 {
1510 for (capture *c = capt; c != NULL; c = c->next)
1511 if (c->srcs_file.is_set ())
1512 {
1513 srcs->add (c->srcs_file.get ());
1514 ok = true;
1515 }
1516 srcs->done ();
1517 delete_capture (capt);
1518 capt = gdb->capture_cmd ("server info line main");
1519 if (capt != NULL && capt->source_file.is_set ())
1520 srcs->select (_getname (capt->source_file.get ()));
1521 delete_capture (capt);
1522 }
1523 if (ok)
1524 srcs->show (true);
1525 }
1526 else
1527 {
1528 unlock ();
1529 set_title ("pmgdb");
1530 }
1531}
1532
1533
1534void command_window::where ()
1535{
1536 capture *capt = gdb->capture_cmd ("server info line *$pc");
1537 if (capt != NULL && capt->source_file.is_set ())
1538 show_source (NULL, capt->source_file.get (), true,
1539 capt->source_lineno.get ());
1540 else
1541 show_source (NULL, NULL, false, -1);
1542 delete_capture (capt);
1543}
1544
1545
1546void command_window::update_registers ()
1547{
1548 capture *capt = gdb->capture_cmd ("server info registers");
1549 if (capt != NULL)
1550 reg->update (gdb->get_output ());
1551 delete_capture (capt);
1552}
1553
1554
1555void command_window::help_disable (const pmframe *frame)
1556{
1557 frame->menu_enable (IDM_HELP_EXT, false, true);
1558 frame->menu_enable (IDM_HELP_HELP, false, true);
1559 frame->menu_enable (IDM_HELP_KEYS, false, true);
1560 frame->menu_enable (IDM_HELP_INDEX, false, true);
1561 frame->menu_enable (IDM_HELP_CONTENTS, false, true);
1562 frame->menu_enable (IDM_TUTORIAL, false, true);
1563}
1564
1565
1566void command_window::associate_help (HWND hwnd)
1567{
1568 if (get_hwndHelp () != NULLHANDLE)
1569 WinAssociateHelpInstance (get_hwndHelp (), hwnd);
1570}
1571
1572
1573void command_window::run_command ()
1574{
1575 if (!breakpoints.any_enabled ())
1576 gdb->queue_cmd ("server break main");
1577 gdb->queue_cmd ("server run");
1578}
1579
1580
1581void command_window::prepare_run ()
1582{
1583 gdb->prepare_run ();
1584 HWND hwndLock = WinQueryFocus (HWND_DESKTOP);
1585 if (hwndLock == NULLHANDLE)
1586 hwndLock = get_hwndClient ();
1587 pmdbg.set_window (hwndLock);
1588 pmdbg_start ();
1589}
1590
1591
1592void command_window::pmdbg_start ()
1593{
1594 if (same_tid ())
1595 pmdbg.start ();
1596 else
1597 WinSendMsg (get_hwndClient (), UWM_PMDBG_START, 0, 0);
1598}
1599
1600
1601void command_window::pmdbg_stop ()
1602{
1603 if (same_tid ())
1604 pmdbg.stop ();
1605 else
1606 WinSendMsg (get_hwndClient (), UWM_PMDBG_STOP, 0, 0);
1607}
1608
1609
1610void command_window::pmdbg_term ()
1611{
1612 if (same_tid ())
1613 pmdbg.term ();
1614 else
1615 WinSendMsg (get_hwndClient (), UWM_PMDBG_TERM, 0, 0);
1616}
Note: See TracBrowser for help on using the repository browser.