source: vendor/emx/current/src/pmgdb/source.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: 16.1 KB
Line 
1/* source.cc
2 Copyright (c) 1996 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_WIN
24#include <os2.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <io.h>
29#include <fcntl.h>
30#include "string.h"
31#include "pmapp.h"
32#include "pmframe.h"
33#include "pmtxt.h"
34#include "pmtty.h"
35#include "pmgdb.h"
36#include "help.h"
37#include "breakpoi.h"
38#include "source.h"
39#include "display.h"
40#include "annotati.h"
41#include "capture.h"
42#include "gdbio.h"
43#include "command.h"
44
45#define LINENO_WIDTH 6
46#define SOURCE_COLUMN (LINENO_WIDTH + 4)
47
48source_window::source_window (pmapp *in_app, unsigned in_id,
49 const char *fontnamesize,
50 const char *short_fname, const char *long_fname,
51 command_window *in_cmd, gdbio *in_gdb)
52 : pmtxt (in_app, in_id, FCF_SHELLPOSITION, NULL, fontnamesize)
53{
54 cmd = in_cmd; gdb = in_gdb;
55 short_filename = short_fname;
56 long_filename = long_fname;
57
58 astring title;
59 title = "pmgdb - ";
60 title.append (short_filename);
61 set_title (title);
62
63 set_keys_help_id (HELP_SRC_KEYS);
64
65 hilite_attr = get_default_attr ();
66 set_fg_color (hilite_attr, CLR_WHITE);
67 set_bg_color (hilite_attr, CLR_BLACK);
68
69 sel_attr = get_default_attr ();
70 set_fg_color (sel_attr, CLR_BLACK);
71 set_bg_color (sel_attr, CLR_PALEGRAY);
72
73 bpt_attr = get_default_attr ();
74 set_fg_color (bpt_attr, CLR_WHITE);
75 set_bg_color (bpt_attr, CLR_RED);
76
77 sel_bpt_attr = get_default_attr ();
78 set_fg_color (sel_bpt_attr, CLR_WHITE);
79 set_bg_color (sel_bpt_attr, CLR_PINK);
80
81 // Initialize menu
82 WinPostMsg (get_hwndClient (), UWM_STATE, MPFROMLONG (~0), 0);
83
84 load ();
85 set_font (*cmd);
86 show (true);
87}
88
89
90source_window::~source_window ()
91{
92}
93
94
95void source_window::load ()
96{
97 char buf[max_line_len+2]; // Line read from source file
98 char pfx[10]; // Line number
99 int c;
100
101 delete_all ();
102 cur_lineno = -1; sel_lineno = -1;
103 exp_lineno = -1; find_string = "";
104 menu_enable (IDM_FINDNEXT, false);
105 menu_enable (IDM_FINDPREV, false);
106
107 FILE *f = fopen (long_filename, "r");
108 if (f == NULL)
109 {
110 // TODO: Use GDB's value of `set directory'
111 // TODO: Dialog box, asking for file name
112 strcpy (buf, "Cannot open file");
113 put (0, 0, strlen (buf), buf, true);
114 }
115 else
116 {
117 int y = 0;
118 while (fgets (buf, sizeof (buf), f) != NULL)
119 {
120 size_t len = strlen (buf);
121 if (len > 0 && buf[len-1] == '\n')
122 --len;
123 else
124 {
125 // Line too long, skip rest
126 do
127 {
128 c = fgetc (f);
129 } while (c != EOF && c != '\n');
130 }
131
132 // Insert line number
133 int pfx_len = sprintf (pfx, "%*d ", LINENO_WIDTH, y + 1);
134 put (y, 0, pfx_len, pfx, false);
135 put_tab (y, LINENO_WIDTH + 1, false);
136 put_vrule (y, LINENO_WIDTH + 2, false);
137
138 // Insert source line
139 char *tab = (char *)memchr (buf, '\t', len);
140 if (tab == NULL)
141 put (y, SOURCE_COLUMN, len, buf, false);
142 else
143 {
144 // Expand TABs
145 int x = 0;
146 size_t i = 0;
147 while (tab != NULL)
148 {
149 size_t copy = tab - (buf + i);
150 if (copy != 0)
151 {
152 put (y, SOURCE_COLUMN + x, copy, buf + i, false);
153 i += copy; x += copy;
154 }
155 int tab_width = (x | 7) + 1 - x;
156 put (y, SOURCE_COLUMN + x, tab_width, " ", false);
157 ++i; x += tab_width;
158 tab = (char *)memchr (buf + i, '\t', len - i);
159 }
160 if (i < len)
161 put (y, SOURCE_COLUMN + x, len - i, buf + i, false);
162 }
163 ++y;
164 }
165 // TODO: ferror()
166 fclose (f);
167 }
168 cmd->get_breakpoints (this, false);
169}
170
171
172void source_window::show_line (int lineno)
173{
174 if (lineno != cur_lineno)
175 {
176 if (cur_lineno != -1)
177 {
178 put (cur_lineno - 1, SOURCE_COLUMN - 1, max_line_len,
179 get_default_attr (), true);
180 set_eol_attr (cur_lineno - 1, get_default_attr (), true);
181 }
182 if (lineno != -1)
183 {
184 put (lineno - 1, SOURCE_COLUMN - 1, max_line_len, hilite_attr, true);
185 set_eol_attr (lineno - 1, hilite_attr, true);
186 }
187 cur_lineno = lineno;
188 if (lineno == exp_lineno)
189 exp_lineno = -1;
190 }
191 if (lineno != -1)
192 parent::show_line (lineno - 1, 1, get_window_lines () * 2 / 3);
193}
194
195
196void source_window::select_line (int lineno)
197{
198 if (lineno != sel_lineno)
199 {
200 if (sel_lineno != -1)
201 {
202 const breakpoint *bpt
203 = cmd->breakpoints.find (short_filename, sel_lineno);
204 put (sel_lineno - 1, 0, LINENO_WIDTH + 2,
205 bpt != NULL ? bpt_attr : get_default_attr (), true);
206 }
207 if (lineno != -1)
208 {
209 const breakpoint *bpt
210 = cmd->breakpoints.find (short_filename, lineno);
211 put (lineno - 1, 0, LINENO_WIDTH + 2,
212 bpt != NULL ? sel_bpt_attr : sel_attr, true);
213 }
214 sel_lineno = lineno;
215 }
216}
217
218
219ULONG source_window::selected_addr ()
220{
221 if (sel_lineno == -1)
222 return 0;
223 return gdb->address_of_line (short_filename, sel_lineno);
224}
225
226
227MRESULT source_window::goto_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
228{
229 char buf[80];
230
231 switch (msg)
232 {
233 case WM_INITDLG:
234 dlg_sys_menu (hwnd);
235 WinSetWindowPtr (hwnd, QWL_USER, this);
236 break;
237
238 case WM_COMMAND:
239 switch (SHORT1FROMMP (mp1))
240 {
241 case DID_OK:
242 WinQueryDlgItemText (hwnd, IDC_LINENO, sizeof (buf), (PSZ)buf);
243 int lineno = atoi (buf);
244 if (lineno > 0)
245 parent::show_line (lineno - 1, 1, get_window_lines () / 2);
246 WinDismissDlg (hwnd, DID_OK);
247 return 0;
248 }
249 break;
250 }
251 return WinDefDlgProc (hwnd, msg, mp1, mp2);
252}
253
254
255MRESULT EXPENTRY dlg_goto (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
256{
257 source_window *p;
258
259 if (msg == WM_INITDLG)
260 p = (source_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
261 else
262 p = (source_window *)WinQueryWindowPtr (hwnd, QWL_USER);
263 return p->goto_msg (hwnd, msg, mp1, mp2);
264}
265
266
267MRESULT source_window::find_msg (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
268{
269 char buf[200];
270
271 switch (msg)
272 {
273 case WM_INITDLG:
274 dlg_sys_menu (hwnd);
275 WinSendDlgItemMsg (hwnd, IDC_STRING, EM_SETTEXTLIMIT,
276 MPFROMSHORT (sizeof (buf) - 1), 0);
277 WinSetDlgItemText (hwnd, IDC_STRING, (PCSZ)find_string);
278 WinSetWindowPtr (hwnd, QWL_USER, this);
279 break;
280
281 case WM_COMMAND:
282 switch (SHORT1FROMMP (mp1))
283 {
284 case DID_OK:
285 WinQueryDlgItemText (hwnd, IDC_STRING, sizeof (buf), (PSZ)buf);
286 if (buf[0] != 0)
287 {
288 find_string = buf;
289 WinDismissDlg (hwnd, DID_OK);
290 }
291 else
292 WinDismissDlg (hwnd, DID_CANCEL);
293 return 0;
294 }
295 break;
296 }
297 return WinDefDlgProc (hwnd, msg, mp1, mp2);
298}
299
300
301MRESULT EXPENTRY dlg_find (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
302{
303 source_window *p;
304
305 if (msg == WM_INITDLG)
306 p = (source_window *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
307 else
308 p = (source_window *)WinQueryWindowPtr (hwnd, QWL_USER);
309 return p->find_msg (hwnd, msg, mp1, mp2);
310}
311
312
313MRESULT source_window::wm_activate (HWND hwnd, ULONG msg,
314 MPARAM mp1, MPARAM mp2)
315{
316 if (SHORT1FROMMP (mp1))
317 cmd->associate_help (get_hwndFrame ());
318 return WinDefWindowProc (hwnd, msg, mp1, mp2);
319}
320
321
322MRESULT source_window::wm_char (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
323{
324 if ((SHORT1FROMMP (mp1) & (KC_VIRTUALKEY|KC_KEYUP)) == KC_VIRTUALKEY)
325 {
326 HWND hwndTarget = NULLHANDLE;
327 switch (SHORT2FROMMP (mp2))
328 {
329 case VK_UP:
330 case VK_DOWN:
331 hwndTarget = get_hwndVbar ();
332 break;
333
334 case VK_PAGEUP:
335 case VK_PAGEDOWN:
336 if (SHORT1FROMMP (mp1) & KC_CTRL)
337 hwndTarget = get_hwndHbar ();
338 else
339 hwndTarget = get_hwndVbar ();
340 break;
341
342 case VK_LEFT:
343 case VK_RIGHT:
344 hwndTarget = get_hwndHbar ();
345 break;
346 }
347 if (hwndTarget != NULLHANDLE && WinIsWindowEnabled (hwndTarget))
348 WinPostMsg (hwndTarget, msg, mp1, mp2);
349 }
350 return WinDefWindowProc (hwnd, msg, mp1, mp2);
351}
352
353
354MRESULT source_window::wm_command (HWND hwnd, ULONG msg,
355 MPARAM mp1, MPARAM mp2)
356{
357 ULONG addr;
358 pm_create create;
359
360 switch (SHORT1FROMMP (mp1))
361 {
362 case IDM_GOTO:
363 create.cb = sizeof (create);
364 create.ptr = (void *)this;
365 WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_goto, 0, IDD_GOTO,
366 &create);
367 return 0;
368
369 case IDM_FIND:
370 create.cb = sizeof (create);
371 create.ptr = (void *)this;
372 if (WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_find, 0, IDD_FIND,
373 &create) == DID_OK)
374 find (true, true);
375 return 0;
376
377 case IDM_FINDNEXT:
378 find (false, true);
379 return 0;
380
381 case IDM_FINDPREV:
382 find (false, false);
383 return 0;
384
385 case IDM_JUMP:
386 // TODO: Don't do this in the PM thread (time!)
387 addr = selected_addr ();
388 if (addr == 0 || !gdb->call_cmd ("server set var $pc=0x%lx", addr))
389 WinAlarm (HWND_DESKTOP, WA_ERROR);
390 else
391 cmd->where ();
392 return 0;
393
394 case IDM_UNTIL:
395 // TODO: Don't do this in the PM thread (time!)
396 addr = selected_addr ();
397 if (addr == 0)
398 WinAlarm (HWND_DESKTOP, WA_ERROR);
399 else
400 {
401 gdb->prepare_run ();
402 gdb->send_cmd ("server until *0x%lx", addr);
403 }
404 return 0;
405
406 case IDM_DSP_SHOW:
407 cmd->dsp->show (true);
408 return 0;
409
410 case IDM_DSP_ADD:
411 if (cmd->dsp->add (hwnd))
412 cmd->dsp->show (true);
413 return 0;
414
415 case IDM_BRKPT_LINE:
416 cmd->brk->add_line (short_filename, sel_lineno);
417 return 0;
418
419 default:
420 return cmd->wm_command (hwnd, msg, mp1, mp2);
421 }
422}
423
424
425bool source_window::wm_user (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
426{
427 unsigned change;
428
429 if (parent::wm_user (hwnd, msg, mp1, mp2))
430 return true;
431 switch (msg)
432 {
433 case UWM_STATE:
434 change = LONGFROMMP (mp1);
435 if (change & command_window::GSC_PROMPT)
436 menu_enable (IDM_RUNMENU, gdb->is_ready ());
437 if (change & command_window::GSC_RUNNING)
438 {
439 if (gdb->is_nochild ())
440 show_line (-1);
441 // TODO: IDM_GO
442 bool running = !gdb->is_nochild ();
443 menu_enable (IDM_STEPOVER, running);
444 menu_enable (IDM_STEPINTO, running);
445 menu_enable (IDM_ISTEPOVER, running);
446 menu_enable (IDM_ISTEPINTO, running);
447 // TODO:
448 menu_enable (IDM_UNTIL, running);
449 menu_enable (IDM_JUMP, running);
450 menu_enable (IDM_FINISH, running);
451 }
452 if (change & command_window::GSC_EXEC_FILE)
453 {
454 menu_enable (IDM_RESTART, cmd->get_debuggee () != NULL);
455 menu_enable (IDM_GO, cmd->get_debuggee () != NULL);
456 }
457 return true;
458
459 default:
460 return false;
461 }
462}
463
464
465MRESULT source_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
466{
467 WinPostMsg (cmd->get_hwndClient (), UWM_CLOSE_SRC, MPFROMP (this), 0);
468 return 0;
469}
470
471
472static bool is_symbol (int c)
473{
474 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
475}
476
477
478void source_window::button1_lineno (int line, int clicks)
479{
480 int lineno = line + 1;
481 if (clicks == 0)
482 {
483 if (lineno == sel_lineno)
484 select_line (-1);
485 else
486 select_line (lineno);
487 }
488 else if (clicks == 2)
489 {
490 const breakpoint *brk
491 = cmd->breakpoints.find (short_filename, lineno);
492 // TODO: enabled/disabled
493 if (brk != NULL)
494 gdb->send_cmd ("server delete %d", brk->get_number ());
495 else
496 gdb->send_cmd ("server break %s:%d",
497 (const char *)short_filename, lineno);
498 }
499}
500
501
502void source_window::button1_source (int line, int column, int clicks)
503{
504 if (clicks == 2)
505 {
506 if (exp_lineno != -1)
507 {
508 put (exp_lineno - 1, exp_column, exp_len,
509 exp_lineno == cur_lineno ? hilite_attr : get_default_attr (),
510 true);
511 exp_lineno = -1;
512 }
513 if (is_symbol (get_char (line, column)))
514 {
515 int start = column;
516 while (start > 0)
517 {
518 int c = get_char (line, start - 1);
519 if (is_symbol (c))
520 --start;
521 // TODO: blanks
522 else if (c == '.'
523 && is_symbol (get_char (line, start - 2)))
524 start -= 2;
525 // TODO: blanks
526 else if (c == '>'
527 && get_char (line, start - 2) == '-'
528 && is_symbol (get_char (line, start - 3)))
529 start -= 3;
530 else
531 break;
532 }
533 int end = column + 1;
534 for (;;)
535 {
536 int c = get_char (line, end);
537 if (is_symbol (c) || (c >= '0' && c <= '9'))
538 ++end;
539 else
540 break;
541 }
542 char *buf = (char *)alloca (end - start + 1);
543 if (get_string (line, start, buf, end - start))
544 {
545 exp_lineno = line + 1;
546 exp_column = start; exp_len = end - start;
547 put (line, start, exp_len, sel_attr, true);
548 // TODO: Context (class, function, ...)
549 gdb->send_cmd ("server display %s", buf);
550 cmd->dsp->show (true);
551 }
552 }
553 }
554}
555
556
557void source_window::button_event (int line, int column, int, int button,
558 int clicks)
559{
560 if (line >= 0 && column >= 0 && button == 1)
561 {
562 // TODO: Context menu (run editor, set/edit breakpoint, ...)
563 if (column < LINENO_WIDTH + 2)
564 button1_lineno (line, clicks);
565 else if (column >= SOURCE_COLUMN - 1)
566 button1_source (line, column, clicks);
567 }
568}
569
570
571void source_window::set_breakpoint (int lineno, bool set, bool paint)
572{
573 put (lineno - 1, 0, LINENO_WIDTH + 2,
574 set ? bpt_attr : lineno == sel_lineno ? sel_attr : get_default_attr (),
575 paint);
576}
577
578
579// TODO: Don't do this in the PM thread
580
581void source_window::find (bool start, bool forward)
582{
583 capture *capt = gdb->capture_cmd ("server list %s:%d,1",
584 (const char *)short_filename,
585 start ? 1 : find_lineno);
586 delete_capture (capt);
587 capt = gdb->capture_cmd ("server %s %s",
588 forward ? "search" : "reverse-search",
589 (const char *)find_string);
590 long n;
591 if (capt != NULL && (n = strtol (gdb->get_output (), NULL, 10)) >= 1)
592 {
593 find_lineno = (int)n;
594 select_line ((int)n);
595 parent::show_line (n - 1, 1, get_window_lines () / 2);
596 menu_enable (IDM_FINDNEXT, true);
597 menu_enable (IDM_FINDPREV, !start);
598 }
599 else
600 {
601 WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
602 (PSZ)"Not found.", (PSZ)"pmgdb", 0,
603 MB_MOVEABLE | MB_OK | MB_ICONEXCLAMATION);
604 if (forward || start)
605 menu_enable (IDM_FINDNEXT, false);
606 if (!forward || start)
607 menu_enable (IDM_FINDPREV, false);
608 }
609 delete_capture (capt);
610}
Note: See TracBrowser for help on using the repository browser.