home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / emxtutor.zip / emxsrcd1.zip / emx / src / pmgdb / breakpoi.cc < prev    next >
C/C++ Source or Header  |  1996-09-08  |  24KB  |  856 lines

  1. /* breakpoi.cc
  2.    Copyright (c) 1996 Eberhard Mattes
  3.  
  4. This file is part of pmgdb.
  5.  
  6. pmgdb 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 2, or (at your option)
  9. any later version.
  10.  
  11. pmgdb 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 pmgdb; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21.  
  22. #define INCL_WIN
  23. #include <os2.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>              // sprintf()
  26. #include <stdarg.h>
  27. #include <string.h>
  28. #include "string.h"
  29. #include "pmapp.h"
  30. #include "pmframe.h"
  31. #include "pmtxt.h"
  32. #include "pmtty.h"
  33. #include "pmgdb.h"
  34. #include "help.h"
  35. #include "breakpoi.h"
  36. #include "srcfiles.h"
  37. #include "annotati.h"
  38. #include "capture.h"
  39. #include "gdbio.h"
  40. #include "command.h"
  41.  
  42. breakpoint::breakpoint ()
  43. {
  44.   number = 0;
  45.   type = BPT_UNKNOWN;
  46.   disposition = BPD_UNKNOWN;
  47.   enable = false;
  48.   address = 0;
  49.   lineno = 0;
  50.   ignore = 0;
  51. }
  52.  
  53.  
  54. breakpoint::breakpoint (const breakpoint &src)
  55. {
  56.   copy (src);
  57. }
  58.  
  59.  
  60. breakpoint &breakpoint::operator = (const breakpoint &src)
  61. {
  62.   copy (src);
  63.   return *this;
  64. }
  65.  
  66.  
  67. // Note: Does not copy next:
  68.  
  69. void breakpoint::copy (const breakpoint &src)
  70. {
  71.   number = src.number;
  72.   type = src.type;
  73.   disposition = src.disposition;
  74.   enable = src.enable;
  75.   address = src.address;
  76.   source = src.source;
  77.   lineno = src.lineno;
  78.   condition = src.condition;
  79.   ignore = src.ignore;
  80. }
  81.  
  82.  
  83. breakpoint::~breakpoint ()
  84. {
  85. }
  86.  
  87.  
  88. bool breakpoint::operator == (const breakpoint b) const
  89. {
  90.   return (number == b.number
  91.           && type == b.type
  92.           && disposition == b.disposition
  93.           && enable == b.enable
  94.           && address == b.address
  95.           && lineno == b.lineno
  96.           && source == b.source
  97.           && condition == b.condition
  98.           && ignore == b.ignore);
  99. }
  100.  
  101.  
  102. void breakpoint::set_disposition (const char *s)
  103. {
  104.   if (s[0] == 'd' && s[1] == 'e') // "del"
  105.     disposition = BPD_DEL;
  106.   else if (s[0] == 'd' && s[1] == 'i') // "dis"
  107.     disposition = BPD_DIS;
  108.   else if (s[0] == 'k')
  109.     disposition = BPD_KEEP;     // "keep"
  110.   else
  111.     disposition = BPD_UNKNOWN;
  112. }
  113.  
  114.  
  115. const char *breakpoint::get_disposition_as_string () const
  116. {
  117.   switch (disposition)
  118.     {
  119.     case BPD_DEL:
  120.       return "del";
  121.     case BPD_DIS:
  122.       return "dis";
  123.     case BPD_KEEP:
  124.       return "keep";
  125.     default:
  126.       return "?";
  127.     }
  128. }
  129.  
  130.  
  131. bool breakpoint::set_from_capture (const capture &capt)
  132. {
  133.   if (!(capt.bpt_number.is_set ()
  134.         && capt.bpt_enable.is_set ()
  135.         && capt.bpt_address.is_set ()
  136.         && capt.bpt_disposition.is_set ()
  137.         && capt.bpt_what.is_set ()))
  138.     return false;
  139.  
  140.   set_number (capt.bpt_number.get ());
  141.   set_address (capt.bpt_address.get ());
  142.   set_enable (capt.bpt_enable.get ());
  143.   set_disposition (capt.bpt_disposition.get ());
  144.   if (capt.bpt_condition.is_set ())
  145.     set_condition (capt.bpt_condition.get ());
  146.   if (capt.bpt_ignore.is_set ())
  147.     set_ignore (capt.bpt_ignore.get ());
  148.   else
  149.     set_ignore (0);
  150.  
  151.   const char *p = capt.bpt_what.get ();
  152.   // "in main at source.c:217 "
  153.   if (strncmp (p, "in ", 3) == 0)
  154.     {
  155.       p += 3;
  156.       char *end = strstr (p, " at ");
  157.       if (end == NULL)
  158.         p = strchr (p, ' ');
  159.       if (end == NULL)
  160.         p = end;
  161.       else
  162.         p = end + 1;
  163.     }
  164.   if (strncmp (p, "at ", 3) == 0)
  165.     {
  166.       p += 3;
  167.       const char *colon = p;
  168.       while (*colon != 0 && *colon != ':' && *colon != ' ' && *colon != '\n')
  169.         ++colon;
  170.       if (*colon == ':')
  171.         {
  172.           char *end;
  173.           long lineno = strtol (colon + 1, &end, 10);
  174.           if (end != colon + 1
  175.               && (*end == ' ' || *end == '\n' || *end == 0))
  176.             {
  177.               set_lineno ((int)lineno);
  178.               set_source (p, colon - p);
  179.             }
  180.         }
  181.     }
  182.   return true;
  183. }
  184.  
  185.  
  186. static const struct
  187. {
  188.   const char *text;
  189.   breakpoint::bpd disp;
  190. } disposition_table[3] =
  191.   {
  192.     {"keep", breakpoint::BPD_KEEP},
  193.     {"dis", breakpoint::BPD_DIS},
  194.     {"del", breakpoint::BPD_DEL}
  195.   };
  196.  
  197. MRESULT breakpoint::breakpoint_msg (HWND hwnd, ULONG msg,
  198.                                     MPARAM mp1, MPARAM mp2)
  199. {
  200.   MRESULT mr;
  201.   HWND hwndTemp;
  202.   static char buf[270];         // TODO: query length, see display_window
  203.   const pm_create *pcreate;
  204.   const source_files_window *srcs;
  205.   int i, sel_idx;
  206.  
  207.   switch (msg)
  208.     {
  209.     case WM_INITDLG:
  210.       pcreate = (const pm_create *)PVOIDFROMMP (mp2);
  211.       srcs = (const source_files_window *)pcreate->ptr2;
  212.       dlg_sys_menu (hwnd);
  213.       WinSetWindowPtr (hwnd, QWL_USER, this);
  214.       WinSendDlgItemMsg (hwnd, IDC_ENABLE, BM_SETCHECK,
  215.                          MPFROMSHORT (enable), NULL);
  216.       hwndTemp = WinWindowFromID (hwnd, IDC_SOURCE);
  217.       i = 0;
  218.       for (source_files_window::iterator s(*srcs); s.ok (); s.next ())
  219.         {
  220.             WinSendMsg (hwndTemp, LM_INSERTITEM, MPFROMSHORT (i),
  221.                         MPFROMP ((const char *)s));
  222.             if (!source.is_null () && strcmp ((const char *)s,
  223.                                               (const char *)source) == 0)
  224.               WinSendMsg (hwndTemp, LM_SELECTITEM,
  225.                           MPFROMSHORT (i), MPFROMSHORT (TRUE));
  226.             ++i;
  227.         }
  228.  
  229.       if (lineno >= 0)
  230.         {
  231.           _itoa (lineno, buf, 10);
  232.           WinSetDlgItemText (hwnd, IDC_LINENO, (PSZ)buf);
  233.         }
  234.       if (ignore != 0)
  235.         {
  236.           _itoa (ignore, buf, 10);
  237.           WinSetDlgItemText (hwnd, IDC_IGNORE, (PSZ)buf);
  238.         }
  239.       if (!condition.is_null ())
  240.         WinSetDlgItemText (hwnd, IDC_CONDITION, condition);
  241.  
  242.       hwndTemp = WinWindowFromID (hwnd, IDC_DISPOSITION);
  243.       sel_idx = -1;             // Keep the compiler happy
  244.       for (i = 0; i < 3; ++i)
  245.         {
  246.           WinSendMsg (hwndTemp, LM_INSERTITEM, MPFROMSHORT (i),
  247.                       MPFROMP (disposition_table[i].text));
  248.           if (disposition_table[i].disp == disposition)
  249.             sel_idx = i;
  250.         }
  251.       WinSendMsg (hwndTemp, LM_SELECTITEM,
  252.                   MPFROMSHORT (sel_idx), MPFROMSHORT (TRUE));
  253.       break;
  254.  
  255.     case WM_COMMAND:
  256.       switch (SHORT1FROMMP (mp1))
  257.         {
  258.         case DID_OK:
  259.           mr = WinSendDlgItemMsg (hwnd, IDC_ENABLE, BM_QUERYCHECK, NULL, NULL);
  260.           enable = (bool)SHORT1FROMMR (mr);
  261.           buf[0] = 0;
  262.           WinQueryDlgItemText (hwnd, IDC_SOURCE, sizeof (buf), (PSZ)buf);
  263.           set_source (buf, strlen (buf));
  264.           buf[0] = 0;
  265.           WinQueryDlgItemText (hwnd, IDC_LINENO, sizeof (buf), (PSZ)buf);
  266.           lineno = atoi (buf);
  267.           buf[0] = 0;
  268.           WinQueryDlgItemText (hwnd, IDC_IGNORE, sizeof (buf), (PSZ)buf);
  269.           ignore = atoi (buf);
  270.           buf[0] = 0;
  271.           WinQueryDlgItemText (hwnd, IDC_CONDITION, sizeof (buf), (PSZ)buf);
  272.           if (buf[0] == 0)      // TODO: Ignore white space
  273.             condition.set_null ();
  274.           else
  275.             set_condition (buf);
  276.           buf[0] = 0;
  277.           WinQueryDlgItemText (hwnd, IDC_DISPOSITION, sizeof (buf), (PSZ)buf);
  278.           for (i = 0; i < 3; ++i)
  279.             if (strcmp (disposition_table[i].text, buf) == 0)
  280.               disposition = disposition_table[i].disp;
  281.           WinDismissDlg (hwnd, DID_OK);
  282.           return 0;
  283.         }
  284.       break;
  285.     }
  286.   return WinDefDlgProc (hwnd, msg, mp1, mp2);
  287. }
  288.  
  289.  
  290. MRESULT EXPENTRY dlg_breakpoint (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  291. {
  292.   breakpoint *p;
  293.  
  294.   if (msg == WM_INITDLG)
  295.     p = (breakpoint *)((struct pm_create *)PVOIDFROMMP (mp2))->ptr;
  296.   else
  297.     p = (breakpoint *)WinQueryWindowPtr (hwnd, QWL_USER);
  298.   return p->breakpoint_msg (hwnd, msg, mp1, mp2);
  299. }
  300.  
  301.  
  302. breakpoint_list::breakpoint_list ()
  303. {
  304.   list = NULL; end = &list;
  305. }
  306.  
  307.  
  308. breakpoint_list::~breakpoint_list ()
  309. {
  310.   delete_all ();
  311. }
  312.  
  313.  
  314. void breakpoint_list::delete_all ()
  315. {
  316.   brkpt_node *next;
  317.   for (brkpt_node *p = list; p != NULL; p = next)
  318.     {
  319.       next = p->next;
  320.       delete p;
  321.     }
  322.   list = NULL; end = &list;
  323. }
  324.  
  325.  
  326. void breakpoint_list::add (const breakpoint &bp)
  327. {
  328.   brkpt_node *node = new brkpt_node (bp);
  329.   *end = node; end = &node->next;
  330. }
  331.  
  332.  
  333. const breakpoint *breakpoint_list::find (ULONG addr) const
  334. {
  335.   for (const brkpt_node *p = list; p != NULL; p = p->next)
  336.     if (p->address == addr)
  337.       return p;
  338.   return NULL;
  339. }
  340.  
  341.  
  342. const breakpoint *breakpoint_list::find (const char *fname, int lineno) const
  343. {
  344.   for (const brkpt_node *p = list; p != NULL; p = p->next)
  345.     if (!p->source.is_null () && p->lineno == lineno
  346.         && _fncmp ((const unsigned char *)p->source,
  347.                    (const unsigned char *)fname) == 0)
  348.       return p;
  349.   return NULL;
  350. }
  351.  
  352.  
  353. const breakpoint *breakpoint_list::get (int n) const
  354. {
  355.   for (const brkpt_node *p = list; p != NULL; p = p->next)
  356.     if (n == 0)
  357.       return p;
  358.     else
  359.       --n;
  360.   return NULL;
  361. }
  362.  
  363.  
  364. void breakpoint_list::steal (breakpoint_list &from)
  365. {
  366.   list = from.list; end = from.end;
  367.   from.list = NULL; from.end = &from.list;
  368. }
  369.  
  370.  
  371. void breakpoint_list::update (const breakpoint_list &old, command_window *cmd,
  372.                               update_fun fun)
  373. {
  374.   const brkpt_node *o = old.list;
  375.   const brkpt_node *n = list;
  376.   int cmp, index = 0;
  377.   while (o != NULL || n != NULL)
  378.     {
  379.       if (o == NULL)
  380.         cmp = 1;
  381.       else if (n == NULL)
  382.         cmp = -1;
  383.       else if (o->get_number () > n->get_number ())
  384.         cmp = 1;
  385.       else if (o->get_number () < n->get_number ())
  386.         cmp = -1;
  387.       else
  388.         cmp = 0;
  389.  
  390.       // TODO: enabled/disabled
  391.  
  392.       if (cmp < 0)
  393.         (cmd->*fun) (index, o, NULL);
  394.       else if (cmp > 0)
  395.         (cmd->*fun) (index++, NULL, n);
  396.       else
  397.         (cmd->*fun) (index++, o, n);
  398.  
  399.       if (cmp >= 0)
  400.         n = n->next;
  401.       if (cmp <= 0)
  402.         o = o->next;
  403.     }
  404. }
  405.  
  406.  
  407. bool breakpoint_list::any_enabled () const
  408. {
  409.   for (const brkpt_node *p = list; p != NULL; p = p->next)
  410.     if (p->enable)
  411.       return true;
  412.   return false;
  413. }
  414.  
  415.  
  416. #define BRK_HEADER_LINES        1
  417.  
  418. breakpoints_window::breakpoints_window (command_window *in_cmd, gdbio *in_gdb,
  419.                                         unsigned in_id,
  420.                                         const char *fontnamesize)
  421.   : pmtxt (in_cmd->get_app (), in_id, FCF_SHELLPOSITION, NULL, fontnamesize)
  422. {
  423.   cmd = in_cmd; gdb = in_gdb;
  424.   sel_line = -1; exp_number = -1;
  425.  
  426.   sel_attr = get_default_attr ();
  427.   set_fg_color (sel_attr, CLR_BLACK);
  428.   set_bg_color (sel_attr, CLR_PALEGRAY);
  429.  
  430.   set_title ("pmgdb - Breakpoints");
  431.   set_keys_help_id (HELP_BRK_KEYS);
  432.  
  433.   add_all ();
  434. }
  435.  
  436.  
  437. breakpoints_window::~breakpoints_window ()
  438. {
  439. }
  440.  
  441.  
  442. void breakpoints_window::add_all ()
  443. {
  444.   const breakpoint_list::brkpt_node *p;
  445.   int line = BRK_HEADER_LINES;
  446.  
  447.   select_line (-1);
  448.   delete_all ();
  449.  
  450.   int x = 0;
  451.   put (0, x, 4, " No ", true); x += 4;
  452.   put_tab (0, x++, true);
  453.   put_vrule (0, x++, true);
  454.   put (0, x, 5, " Ena ", true); x += 5;
  455.   put_tab (0, x++, true);
  456.   put_vrule (0, x++, true);
  457.   put (0, x, 9, " Address ", true); x += 9;
  458.   put_tab (0, x++, true);
  459.   put_vrule (0, x++, true);
  460.   put (0, x, 8, " Source ", true); x += 8;
  461.   put_tab (0, x++, true);
  462.   put_vrule (0, x++, true);
  463.   put (0, x, 6, " Line ", true); x += 6;
  464.   put_tab (0, x++, true);
  465.   put_vrule (0, x++, true);
  466.   put (0, x, 6, " Disp ", true); x += 6;
  467.   put_tab (0, x++, true);
  468.   put_vrule (0, x++, true);
  469.   put (0, x, 6, " Ign ", true); x += 5;
  470.   put_tab (0, x++, true);
  471.   put_vrule (0, x++, true);
  472.   put (0, x, 5, " Cond", true); x += 5;
  473.   underline (0, true, true);
  474.  
  475.   // TODO: iterator
  476.   for (p = cmd->get_breakpoint_list (); p != NULL; p = p->next)
  477.     put_bpt (line++, *p);
  478.   // TODO: Add do_paint argument to pmtxt::delete_all()
  479.   sync ();
  480. }
  481.  
  482.  
  483. void breakpoints_window::update (int index, const breakpoint *old_bpt,
  484.                                  const breakpoint *new_bpt)
  485. {
  486.   int line = index + BRK_HEADER_LINES;
  487.   if (new_bpt == NULL)
  488.     {
  489.       delete_lines (line, 1, true);
  490.       if (sel_line != -1)
  491.         {
  492.           if (line == sel_line)
  493.             {
  494.               sel_line = -1;
  495.               menu_enable (IDM_EDITMENU, false);
  496.             }
  497.           else if (line < sel_line)
  498.             --sel_line;
  499.         }
  500.     }
  501.   else if (old_bpt == NULL)
  502.     {
  503.       insert_lines (line, 1, true);
  504.       put_bpt (line, *new_bpt);
  505.       if (sel_line != -1)
  506.         {
  507.           if (line <= sel_line)
  508.             ++sel_line;
  509.         }
  510.       if (exp_number == new_bpt->get_number ())
  511.         {
  512.           exp_number = -1;
  513.           select_line (line);
  514.         }
  515.     }
  516.   else if (*old_bpt != *new_bpt)
  517.     {
  518.       clear_lines (line, 1, true);
  519.       put_bpt (line, *new_bpt);
  520.       if (sel_line != -1)
  521.         {
  522.           if (line == sel_line)
  523.             {
  524.               sel_line = -1;
  525.               select_line (line);
  526.               menu_enable (IDM_ENABLE, !new_bpt->get_enable ());
  527.               menu_enable (IDM_DISABLE, new_bpt->get_enable ());
  528.             }
  529.         }
  530.     }
  531. }
  532.  
  533.  
  534. MRESULT breakpoints_window::wm_activate (HWND hwnd, ULONG msg,
  535.                                          MPARAM mp1, MPARAM mp2)
  536. {
  537.   if (SHORT1FROMMP (mp1))
  538.     cmd->associate_help (get_hwndFrame ());
  539.   return WinDefWindowProc (hwnd, msg, mp1, mp2);
  540. }
  541.  
  542.  
  543. MRESULT breakpoints_window::wm_close (HWND, ULONG, MPARAM, MPARAM)
  544. {
  545.   show (false);
  546.   return 0;
  547. }
  548.  
  549.  
  550. MRESULT breakpoints_window::wm_command (HWND hwnd, ULONG msg,
  551.                                         MPARAM mp1, MPARAM mp2)
  552. {
  553.   const breakpoint *bpt;
  554.  
  555.   switch (SHORT1FROMMP (mp1))
  556.     {
  557.     case IDM_DELETE:
  558.       bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
  559.       if (bpt == NULL)
  560.         WinAlarm (HWND_DESKTOP, WA_ERROR);
  561.       else
  562.         gdb->send_cmd ("server delete %d", bpt->get_number ());
  563.       return 0;
  564.  
  565.     case IDM_ENABLE:
  566.       bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
  567.       if (bpt == NULL)
  568.         WinAlarm (HWND_DESKTOP, WA_ERROR);
  569.       else
  570.         send_disposition (bpt->number, bpt->disposition, true);
  571.       return 0;
  572.  
  573.     case IDM_DISABLE:
  574.       bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
  575.       if (bpt == NULL)
  576.         WinAlarm (HWND_DESKTOP, WA_ERROR);
  577.       else
  578.         send_disposition (bpt->number, bpt->disposition, false);
  579.       return 0;
  580.  
  581.     case IDM_BRKPT_LINE:
  582.       add_line ();
  583.       return 0;
  584.  
  585.     case IDM_REFRESH:
  586.       cmd->get_breakpoints ();
  587.       return 0;
  588.  
  589.     case IDM_MODIFY:
  590.       bpt = cmd->get_breakpoint (sel_line - BRK_HEADER_LINES);
  591.       if (bpt == NULL)
  592.         WinAlarm (HWND_DESKTOP, WA_ERROR);
  593.       else
  594.         {
  595.           breakpoint b = *bpt;
  596.           if (dialog (&b))
  597.             {
  598.               // TODO: bpt might have gone away in the meantime, UWM_STATE!
  599.               // TODO: check values
  600.               // TODO: Check type
  601.               if (b.source != bpt->source || b.lineno != bpt->lineno)
  602.                 {
  603.                   capture *capt;
  604.                   capt = gdb->capture_cmd ("server break %s:%d",
  605.                                            b.get_source (), b.lineno);
  606.                   if (capt != NULL)
  607.                     {
  608.                       if (capt->bpt_number.is_set ())
  609.                         {
  610.                           int number = capt->bpt_number.get ();
  611.                           if (gdb->send_cmd ("server delete %d", bpt->number))
  612.                             {
  613.                               send_disposition (number, b.disposition,
  614.                                                 b.enable);
  615.                               if (!b.condition.is_null ())
  616.                                 gdb->queue_cmd ("server condition %d %s",
  617.                                                 number, b.get_condition ());
  618.                               if (b.ignore != 0)
  619.                                 gdb->queue_cmd ("server ignore %d %d",
  620.                                                 number, b.ignore);
  621.                               exp_number = number;
  622.                             }
  623.                         }
  624.                       else if (capt->error.is_set ())
  625.                         cmd->capture_error (capt);
  626.                       delete_capture (capt);
  627.                     }
  628.                 }
  629.               else
  630.                 {
  631.                   if (b.disposition != bpt->disposition
  632.                       || b.enable != bpt->enable)
  633.                     send_disposition (b.number, b.disposition, b.enable);
  634.                   if (b.condition != bpt->condition)
  635.                     gdb->queue_cmd ("server condition %d %s", b.number,
  636.                                     (b.condition.is_null ()
  637.                                      ? "" : b.get_condition ()));
  638.                   if (b.ignore != bpt->ignore)
  639.                     gdb->queue_cmd ("server ignore %d %d", b.number, b.ignore);
  640.                 }
  641.             }
  642.         }
  643.       return 0;
  644.  
  645.     default:
  646.       return cmd->wm_command (hwnd, msg, mp1, mp2);
  647.     }
  648. }
  649.  
  650.  
  651. void breakpoints_window::put_bpt (int line, const breakpoint &bpt)
  652. {
  653.   char buf[400];
  654.   int x = 0, len;
  655.  
  656.   len = snprintf (buf, sizeof (buf), " %d ", bpt.get_number ());
  657.   put (line, x, len, buf, true); x += len;
  658.   put_tab (line, x++, true);
  659.   put_vrule (line, x++, true);
  660.  
  661.   len = snprintf (buf, sizeof (buf), " %c ", bpt.get_enable () ? 'y' : 'n');
  662.   put (line, x, len, buf, true); x += len;
  663.   put_tab (line, x++, true);
  664.   put_vrule (line, x++, true);
  665.  
  666.   len = snprintf (buf, sizeof (buf), " 0x%.8lx ", bpt.get_address ());
  667.   put (line, x, len, buf, true); x += len;
  668.   put_tab (line, x++, true);
  669.   put_vrule (line, x++, true);
  670.  
  671.   len = snprintf (buf, sizeof (buf), " %s ",
  672.                   bpt.get_source () != NULL ? bpt.get_source () : "-");
  673.   put (line, x, len, buf, true); x += len;
  674.   put_tab (line, x++, true);
  675.   put_vrule (line, x++, true);
  676.  
  677.   len = snprintf (buf, sizeof (buf), " %d ", bpt.get_lineno ());
  678.   put (line, x, len, buf, true); x += len;
  679.   put_tab (line, x++, true);
  680.   put_vrule (line, x++, true);
  681.  
  682.   len = snprintf (buf, sizeof (buf), " %s ",
  683.                   bpt.get_disposition_as_string ());
  684.   put (line, x, len, buf, true); x += len;
  685.   put_tab (line, x++, true);
  686.   put_vrule (line, x++, true);
  687.  
  688.   if (bpt.get_ignore () == 0)
  689.     len = snprintf (buf, sizeof (buf), " - ");
  690.   else
  691.     len = snprintf (buf, sizeof (buf), " %d ", bpt.get_ignore ());
  692.   put (line, x, len, buf, true); x += len;
  693.   put_tab (line, x++, true);
  694.   put_vrule (line, x++, true);
  695.  
  696.   len = snprintf (buf, sizeof (buf), " %s",
  697.                   bpt.get_condition () != NULL ? bpt.get_condition () : "-");
  698.   put (line, x, len, buf, true); x += len;
  699. }
  700.  
  701.  
  702. void breakpoints_window::select_line (int line, bool toggle)
  703. {
  704.   const breakpoint *bpt;
  705.   if (toggle && line != -1 && line == sel_line)
  706.     line = -1;
  707.   if (line == -1)
  708.     bpt = NULL;
  709.   else
  710.     {
  711.       bpt = cmd->get_breakpoint (line - BRK_HEADER_LINES);
  712.       if (bpt == NULL) line = -1;
  713.     }
  714.   if (line != sel_line)
  715.     {
  716.       if (sel_line != -1)
  717.         {
  718.           put (sel_line, 0, max_line_len, get_default_attr (), true);
  719.           set_eol_attr (sel_line, get_default_attr (), true);
  720.         }
  721.       if (line != -1)
  722.         {
  723.           put (line, 0, max_line_len, sel_attr, true);
  724.           set_eol_attr (line, sel_attr, true);
  725.         }
  726.       sel_line = line;
  727.     }
  728.   if (line != -1)
  729.     {
  730.       menu_enable (IDM_ENABLE, !bpt->get_enable ());
  731.       menu_enable (IDM_DISABLE, bpt->get_enable ());
  732.       show_line (line, 1, 1);
  733.     }
  734.   menu_enable (IDM_EDITMENU, line != -1);
  735. }
  736.  
  737.  
  738. void breakpoints_window::button_event (int line, int column, int tab,
  739.                                        int button, int clicks)
  740. {
  741.   if (line >= 0 && column >= 0)
  742.     {
  743.       if (clicks == 1 && button == 1)
  744.         {
  745.           // TODO: Context menu
  746.           select_line (line, true);
  747.         }
  748.       else if (clicks == 2 && button == 1 && tab == 1)
  749.         {
  750.           const breakpoint *p = cmd->get_breakpoint (line - BRK_HEADER_LINES);
  751.           if (p == NULL)
  752.             WinAlarm (HWND_DESKTOP, WA_ERROR);
  753.           else
  754.             {
  755.               gdb->send_cmd ("server %s %d",
  756.                              p->get_enable () ? "disable" : "enable",
  757.                              p->get_number ());
  758.               select_line (line);
  759.             }
  760.         }
  761.       else if (clicks == 2 && button == 1 && tab >= 3 && tab <= 4)
  762.         {
  763.           show_source (line);
  764.           select_line (line);
  765.         }
  766.       else if (clicks == 2)
  767.         {
  768.           // TODO: Double clicking on any other field should change that field
  769.           select_line (line);
  770.         }
  771.     }
  772.   else
  773.     select_line (-1);
  774. }
  775.  
  776.  
  777. void breakpoints_window::show_source (int line)
  778. {
  779.   const breakpoint *bpt = cmd->get_breakpoint (line - BRK_HEADER_LINES);
  780.   if (bpt != NULL && bpt->get_source () != NULL)
  781.     cmd->show_source (bpt->get_source (), NULL, true, bpt->get_lineno());
  782. }
  783.  
  784.  
  785. bool breakpoints_window::dialog (breakpoint *bpt)
  786. {
  787.   pm_create create;
  788.  
  789.   create.cb = sizeof (create);
  790.   create.ptr = (void *)bpt;
  791.   create.ptr2 = (void *)cmd->get_srcs ();
  792.   // TODO: Breakpoint type
  793.   return WinDlgBox (HWND_DESKTOP, get_hwndClient (), dlg_breakpoint, 0,
  794.                     IDD_BRKPT_LINE, &create) == DID_OK;
  795. }
  796.  
  797.  
  798. void breakpoints_window::add_line (const char *default_source, int line_no)
  799. {
  800.   breakpoint temp;
  801.   // TODO: Breakpoint type
  802.   temp.set_enable (true);
  803.   if (default_source != NULL)
  804.     temp.set_source (default_source, strlen (default_source));
  805.   temp.set_lineno (line_no);
  806.   if (dialog (&temp))
  807.     {
  808.       select_line (-1);
  809.       capture *capt;
  810.       // TODO: Breakpoint type
  811.       // TODO: Check values
  812.       capt = gdb->capture_cmd ("server break %s:%d",
  813.                                temp.get_source (), temp.get_lineno ());
  814.       if (capt != NULL)
  815.         {
  816.           if (capt->bpt_number.is_set ())
  817.             {
  818.               int number = capt->bpt_number.get ();
  819.               send_disposition (number, temp.disposition, temp.enable);
  820.               if (!temp.condition.is_null ())
  821.                 gdb->queue_cmd ("server condition %d %s", number,
  822.                                 temp.get_condition ());
  823.               if (temp.ignore != 0)
  824.                 gdb->queue_cmd ("server ignore %d %d", number, temp.ignore);
  825.               exp_number = number;
  826.             }
  827.           else if (capt->error.is_set ())
  828.             cmd->capture_error (capt);
  829.         }
  830.       delete_capture (capt);
  831.     }
  832. }
  833.  
  834.  
  835. void
  836. breakpoints_window::send_disposition (int number, breakpoint::bpd disposition,
  837.                                       bool enable)
  838. {
  839.   switch (disposition)
  840.     {
  841.     case breakpoint::BPD_KEEP:
  842.       gdb->queue_cmd ("server enable %d", number);
  843.       break;
  844.     case breakpoint::BPD_DIS:
  845.       gdb->queue_cmd ("server enable once %d", number);
  846.       break;
  847.     case breakpoint::BPD_DEL:
  848.       gdb->queue_cmd ("server enable delete %d", number);
  849.       break;
  850.     default:
  851.       break;
  852.     }
  853.   if (!enable)
  854.     gdb->queue_cmd ("server disable %d", number);
  855. }
  856.