Previous 199869 Revisions Next

r35159 Friday 20th February, 2015 at 18:10:14 UTC by Vasantha Crabb
Port Windows debugger to C++, fix some memory leaks, make menus and window resize a bit nicer
[src/osd/modules/debugger]debugwin.c
[src/osd/modules/debugger/win]consolewininfo.c* consolewininfo.h* debugbaseinfo.c* debugbaseinfo.h* debugviewinfo.c* debugviewinfo.h* debugwin.h* debugwininfo.c* debugwininfo.h* disasmbasewininfo.c* disasmbasewininfo.h* disasmviewinfo.c* disasmviewinfo.h* disasmwininfo.c* disasmwininfo.h* editwininfo.c* editwininfo.h* logwininfo.c* logwininfo.h* memoryviewinfo.c* memoryviewinfo.h* memorywininfo.c* memorywininfo.h* uimetrics.c* uimetrics.h*
[src/osd/sdl]sdl.mak
[src/osd/windows]windows.mak winmain.h

trunk/src/osd/modules/debugger/debugwin.c
r243670r243671
11// license:BSD-3-Clause
2// copyright-holders:Aaron Giles
2// copyright-holders:Aaron Giles, Vas Crabb
33//============================================================
44//
55//  debugwin.c - Win32 debug window handling
r243670r243671
1111
1212#if defined(OSD_WINDOWS) /*|| defined(SDLMAME_WIN32)*/
1313
14// standard windows headers
15#define WIN32_LEAN_AND_MEAN
16#include <windows.h>
17#include <windowsx.h>
18#include <tchar.h>
19#include <commdlg.h>
20#ifdef _MSC_VER
21#include <zmouse.h>
22#endif
14#include "win/debugwin.h"
2315
24// MAME headers
16#include "win/consolewininfo.h"
17#include "win/debugwininfo.h"
18#include "win/disasmwininfo.h"
19#include "win/logwininfo.h"
20#include "win/memorywininfo.h"
21#include "win/uimetrics.h"
22
2523#include "emu.h"
2624#include "uiinput.h"
27#include "imagedev/cassette.h"
2825#include "debugger.h"
29#include "debug/debugvw.h"
30#include "debug/dvdisasm.h"
31#include "debug/dvmemory.h"
32#include "debug/dvstate.h"
33#include "debug/debugvw.h"
34#include "debug/debugcon.h"
35#include "debug/debugcpu.h"
3626
37// MAMEOS headers
38#include "winmain.h"
3927#include "window.h"
28#include "winmain.h"
4029#include "../../windows/input.h"
41#include "strconv.h"
42#include "winutf8.h"
4330
44class debugger_windows : public osd_module, public debug_module
31
32class debugger_windows : public osd_module, public debug_module, protected debugger_windows_interface
4533{
4634public:
47   debugger_windows()
48   : osd_module(OSD_DEBUG_PROVIDER, "windows"), debug_module(),
49      m_machine(NULL)
35   debugger_windows() :
36      osd_module(OSD_DEBUG_PROVIDER, "windows"),
37      debug_module(),
38      m_machine(NULL),
39      m_metrics(),
40      m_waiting_for_debugger(false),
41      m_window_list(),
42      m_main_console(NULL)
5043   {
5144   }
5245
5346   virtual ~debugger_windows() { }
5447
55   virtual int init() { return 0;}
48   virtual int init() { return 0; }
5649   virtual void exit();
5750
5851   virtual void init_debugger(running_machine &machine);
5952   virtual void wait_for_debugger(device_t &device, bool firststop);
6053   virtual void debugger_update();
6154
62private:
63   running_machine *m_machine;
64};
65//============================================================
66//  PARAMETERS
67//============================================================
55protected:
56   virtual running_machine &machine() const { return *m_machine; }
6857
69#define MAX_VIEWS               4
70#define EDGE_WIDTH              3
71#define MAX_EDIT_STRING         256
72#define HISTORY_LENGTH          20
73#define MAX_OTHER_WND           4
58   virtual ui_metrics &metrics() const { return *m_metrics; }
7459
75// debugger window styles
76#define DEBUG_WINDOW_STYLE      (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX)
77#define DEBUG_WINDOW_STYLE_EX   0
60   virtual bool const &waiting_for_debugger() const { return m_waiting_for_debugger; }
61   virtual bool seq_pressed() const;
7862
79// debugger view styles
80#define DEBUG_VIEW_STYLE        WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
81#define DEBUG_VIEW_STYLE_EX     0
63   virtual void create_memory_window() { create_window<memorywin_info>(); }
64   virtual void create_disasm_window() { create_window<disasmwin_info>(); }
65   virtual void create_log_window() { create_window<logwin_info>(); }
66   virtual void remove_window(debugwin_info &info);
8267
83// edit box styles
84#define EDIT_BOX_STYLE          WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
85#define EDIT_BOX_STYLE_EX       0
68   virtual void show_all();
69   virtual void hide_all();
8670
87// combo box styles
88#define COMBO_BOX_STYLE         WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL
89#define COMBO_BOX_STYLE_EX      0
71private:
72   template <typename T> T *create_window();
9073
91// horizontal scroll bar styles
92#define HSCROLL_STYLE           WS_CHILD | WS_VISIBLE | SBS_HORZ
93#define HSCROLL_STYLE_EX        0
74   running_machine            *m_machine;
75   auto_pointer<ui_metrics>   m_metrics;
76   bool                  m_waiting_for_debugger;
77   simple_list<debugwin_info>   m_window_list;
78   consolewin_info            *m_main_console;
79};
9480
95// vertical scroll bar styles
96#define VSCROLL_STYLE           WS_CHILD | WS_VISIBLE | SBS_VERT
97#define VSCROLL_STYLE_EX        0
9881
99
100enum
82void debugger_windows::exit()
10183{
102   ID_NEW_MEMORY_WND = 1,
103   ID_NEW_DISASM_WND,
104   ID_NEW_LOG_WND,
105   ID_RUN,
106   ID_RUN_AND_HIDE,
107   ID_RUN_VBLANK,
108   ID_RUN_IRQ,
109   ID_NEXT_CPU,
110   ID_STEP,
111   ID_STEP_OVER,
112   ID_STEP_OUT,
113   ID_HARD_RESET,
114   ID_SOFT_RESET,
115   ID_EXIT,
84   // loop over windows and free them
85   while (m_window_list.first() != NULL)
86      m_window_list.first()->destroy();
11687
117   ID_1_BYTE_CHUNKS,
118   ID_2_BYTE_CHUNKS,
119   ID_4_BYTE_CHUNKS,
120   ID_8_BYTE_CHUNKS,
121   ID_LOGICAL_ADDRESSES,
122   ID_PHYSICAL_ADDRESSES,
123   ID_REVERSE_VIEW,
124   ID_INCREASE_MEM_WIDTH,
125   ID_DECREASE_MEM_WIDTH,
88   m_main_console = NULL;
89   m_metrics.reset();
90   m_machine = NULL;
91}
12692
127   ID_SHOW_RAW,
128   ID_SHOW_ENCRYPTED,
129   ID_SHOW_COMMENTS,
130   ID_RUN_TO_CURSOR,
131   ID_TOGGLE_BREAKPOINT,
13293
133   ID_DEVICE_OPTIONS  // keep this always at the end
134};
135
136
137
138//============================================================
139//  TYPES
140//============================================================
141
142struct debugview_info;
143class debugwin_info;
144
145
146struct debugview_info
94void debugger_windows::init_debugger(running_machine &machine)
14795{
148   debugwin_info *         owner;
149   debug_view *            view;
150   HWND                    wnd;
151   HWND                    hscroll;
152   HWND                    vscroll;
153};
96   m_machine = &machine;
97   m_metrics.reset(global_alloc(ui_metrics(downcast<windows_options &>(m_machine->options()))));
98}
15499
155100
156class debugwin_info
157{
158public:
159   debugwin_info(running_machine &machine)
160      : m_machine(machine) { }
161
162   running_machine &machine() const { return m_machine; }
163
164   debugwin_info *         next;
165   HWND                    wnd;
166   HWND                    focuswnd;
167   WNDPROC                 handler;
168
169   UINT32                  minwidth, maxwidth;
170   UINT32                  minheight, maxheight;
171   void                    (*recompute_children)(debugwin_info *);
172   void                    (*update_menu)(debugwin_info *);
173
174   int                     (*handle_command)(debugwin_info *, WPARAM, LPARAM);
175   int                     (*handle_key)(debugwin_info *, WPARAM, LPARAM);
176   UINT16                  ignore_char_lparam;
177
178   debugview_info          view[MAX_VIEWS];
179
180   HWND                    editwnd;
181   char                    edit_defstr[256];
182   void                    (*process_string)(debugwin_info *, const char *);
183   WNDPROC                 original_editproc;
184   TCHAR                   history[HISTORY_LENGTH][MAX_EDIT_STRING];
185   int                     history_count;
186   int                     last_history;
187
188   HWND                    otherwnd[MAX_OTHER_WND];
189
190private:
191   running_machine &       m_machine;
192};
193
194
195//============================================================
196//  LOCAL VARIABLES
197//============================================================
198
199static debugwin_info *window_list = NULL;
200static debugwin_info *main_console;
201static UINT32 main_console_regwidth;
202
203static UINT8 waiting_for_debugger;
204
205static HFONT debug_font;
206static UINT32 debug_font_height;
207static UINT32 debug_font_width;
208static UINT32 debug_font_ascent;
209
210static UINT32 hscroll_height;
211static UINT32 vscroll_width;
212
213
214
215//============================================================
216//  PROTOTYPES
217//============================================================
218
219static debugwin_info *debugwin_window_create(running_machine &machine, LPCSTR title, WNDPROC handler);
220static void debugwin_window_free(debugwin_info *info);
221static LRESULT CALLBACK debugwin_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
222
223static void debugwin_view_draw_contents(debugview_info *view, HDC dc);
224static LRESULT CALLBACK debugwin_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
225static void debugwin_view_update(debug_view &view, void *osdprivate);
226static int debugwin_view_create(debugwin_info *info, int which, debug_view_type type);
227
228static LRESULT CALLBACK debugwin_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
229
230//static void generic_create_window(int type);
231static void generic_recompute_children(debugwin_info *info);
232
233static void memory_create_window(running_machine &machine);
234static void memory_recompute_children(debugwin_info *info);
235static void memory_process_string(debugwin_info *info, const char *string);
236static void memory_update_menu(debugwin_info *info);
237static int memory_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam);
238static int memory_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam);
239static void memory_update_caption(running_machine &machine, HWND wnd);
240
241static void disasm_create_window(running_machine &machine);
242static void disasm_recompute_children(debugwin_info *info);
243static void disasm_process_string(debugwin_info *info, const char *string);
244static void disasm_update_menu(debugwin_info *info);
245static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam);
246static int disasm_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam);
247static void disasm_update_caption(running_machine &machine, HWND wnd);
248
249static void console_create_window(running_machine &machine);
250static void console_recompute_children(debugwin_info *info);
251static void console_process_string(debugwin_info *info, const char *string);
252static void console_set_cpu(device_t *device);
253
254static HMENU create_standard_menubar(void);
255static int global_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam);
256static int global_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam);
257static void smart_set_window_bounds(HWND wnd, HWND parent, RECT *bounds);
258static void smart_show_window(HWND wnd, BOOL show);
259static void smart_show_all(BOOL show);
260
261static void image_update_menu(debugwin_info *info);
262
263
264//============================================================
265//  wait_for_debugger
266//============================================================
267
268101void debugger_windows::wait_for_debugger(device_t &device, bool firststop)
269102{
270   MSG message;
271
272103   // create a console window
273   if (main_console == NULL)
274      console_create_window(*m_machine);
104   if (m_main_console == NULL)
105      m_main_console = create_window<consolewin_info>();
275106
276107   // update the views in the console to reflect the current CPU
277   if (main_console != NULL)
278      console_set_cpu(&device);
108   if (m_main_console != NULL)
109      m_main_console->set_cpu(device);
279110
280111   // when we are first stopped, adjust focus to us
281   if (firststop && main_console != NULL)
112   if (firststop && (m_main_console != NULL))
282113   {
283      SetForegroundWindow(main_console->wnd);
114      m_main_console->set_foreground();
284115      if (winwindow_has_focus())
285         SetFocus(main_console->editwnd);
116         m_main_console->set_default_focus();
286117   }
287118
288119   // make sure the debug windows are visible
289   waiting_for_debugger = TRUE;
290   smart_show_all(TRUE);
120   m_waiting_for_debugger = true;
121   show_all();
291122
292123   // run input polling to ensure that our status is in sync
293124   wininput_poll(*m_machine);
294125
295126   // get and process messages
127   MSG message;
296128   GetMessage(&message, NULL, 0, 0);
297129
298130   switch (message.message)
299131   {
300      // check for F10 -- we need to capture that ourselves
301      case WM_SYSKEYDOWN:
302      case WM_SYSKEYUP:
303         if (message.wParam == VK_F4 && message.message == WM_SYSKEYDOWN)
304            SendMessage(GetAncestor(GetFocus(), GA_ROOT), WM_CLOSE, 0, 0);
305         if (message.wParam == VK_F10)
306            SendMessage(GetAncestor(GetFocus(), GA_ROOT), (message.message == WM_SYSKEYDOWN) ? WM_KEYDOWN : WM_KEYUP, message.wParam, message.lParam);
307         break;
132   // check for F10 -- we need to capture that ourselves
133   case WM_SYSKEYDOWN:
134   case WM_SYSKEYUP:
135      if (message.wParam == VK_F4 && message.message == WM_SYSKEYDOWN)
136         SendMessage(GetAncestor(GetFocus(), GA_ROOT), WM_CLOSE, 0, 0);
137      if (message.wParam == VK_F10)
138         SendMessage(GetAncestor(GetFocus(), GA_ROOT), (message.message == WM_SYSKEYDOWN) ? WM_KEYDOWN : WM_KEYUP, message.wParam, message.lParam);
139      break;
308140
309      // process everything else
310      default:
311         winwindow_dispatch_message(*m_machine, &message);
312         break;
141   // process everything else
142   default:
143      winwindow_dispatch_message(*m_machine, &message);
144      break;
313145   }
314146
315147   // mark the debugger as active
316   waiting_for_debugger = FALSE;
148   m_waiting_for_debugger = false;
317149}
318150
319151
320
321//============================================================
322//  debugwin_seq_pressed
323//============================================================
324
325static int debugwin_seq_pressed(running_machine &machine)
326{
327   const input_seq &seq = machine.ioport().type_seq(IPT_UI_DEBUG_BREAK);
328   int result = FALSE;
329   int invert = FALSE;
330   int first = TRUE;
331   int codenum;
332
333   // iterate over all of the codes
334   int length = seq.length();
335   for (codenum = 0; codenum < length; codenum++)
336   {
337      input_code code = seq[codenum];
338
339      // handle NOT
340      if (code == input_seq::not_code)
341         invert = TRUE;
342
343      // handle OR and END
344      else if (code == input_seq::or_code || code == input_seq::end_code)
345      {
346         // if we have a positive result from the previous set, we're done
347         if (result || code == input_seq::end_code)
348            break;
349
350         // otherwise, reset our state
351         result = FALSE;
352         invert = FALSE;
353         first = TRUE;
354      }
355
356      // handle everything else as a series of ANDs
357      else
358      {
359         int vkey = wininput_vkey_for_mame_code(code);
360         int pressed = (vkey != 0 && (GetAsyncKeyState(vkey) & 0x8000) != 0);
361
362         // if this is the first in the sequence, result is set equal
363         if (first)
364            result = pressed ^ invert;
365
366         // further values are ANDed
367         else if (result)
368            result &= pressed ^ invert;
369
370         // no longer first, and clear the invert flag
371         first = invert = FALSE;
372      }
373   }
374
375   // return the result if we queried at least one switch
376   return result;
377}
378
379
380
381//============================================================
382//  debugwin_init_windows
383//============================================================
384
385void debugger_windows::init_debugger(running_machine &machine)
386{
387   static int class_registered;
388
389   m_machine = &machine;
390   // register the window classes
391   if (!class_registered)
392   {
393      WNDCLASS wc = { 0 };
394
395      // initialize the description of the window class
396      wc.lpszClassName    = TEXT("MAMEDebugWindow");
397      wc.hInstance        = GetModuleHandle(NULL);
398      wc.lpfnWndProc      = debugwin_window_proc;
399      wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
400      wc.hIcon            = LoadIcon(wc.hInstance, MAKEINTRESOURCE(2));
401      wc.lpszMenuName     = NULL;
402      wc.hbrBackground    = NULL;
403      wc.style            = 0;
404      wc.cbClsExtra       = 0;
405      wc.cbWndExtra       = 0;
406
407      // register the class; fail if we can't
408      if (!RegisterClass(&wc))
409         fatalerror("Unable to register debug window class\n");
410
411      // initialize the description of the view class
412      wc.lpszClassName    = TEXT("MAMEDebugView");
413      wc.lpfnWndProc      = debugwin_view_proc;
414
415      // register the class; fail if we can't
416      if (!RegisterClass(&wc))
417         fatalerror("Unable to register debug view class\n");
418
419      class_registered = TRUE;
420   }
421
422   // create the font
423   if (debug_font == NULL)
424   {
425      // create a temporary DC
426      HDC temp_dc = GetDC(NULL);
427      TEXTMETRIC metrics;
428      HGDIOBJ old_font;
429
430      if (temp_dc != NULL)
431      {
432         windows_options &options = downcast<windows_options &>(m_machine->options());
433         int size = options.debugger_font_size();
434         TCHAR *t_face;
435
436         // create a standard font
437         t_face = tstring_from_utf8(options.debugger_font());
438         debug_font = CreateFont(-MulDiv(size, GetDeviceCaps(temp_dc, LOGPIXELSY), 72), 0, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE,
439                  ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, t_face);
440         osd_free(t_face);
441         t_face = NULL;
442
443         if (debug_font == NULL)
444            fatalerror("Unable to create debugger font\n");
445
446         // get the metrics
447         old_font = SelectObject(temp_dc, debug_font);
448         if (GetTextMetrics(temp_dc, &metrics))
449         {
450            debug_font_width = metrics.tmAveCharWidth;
451            debug_font_height = metrics.tmHeight;
452            debug_font_ascent = metrics.tmAscent + metrics.tmExternalLeading;
453         }
454         SelectObject(temp_dc, old_font);
455         ReleaseDC(NULL, temp_dc);
456      }
457   }
458
459   // get other metrics
460   hscroll_height = GetSystemMetrics(SM_CYHSCROLL);
461   vscroll_width = GetSystemMetrics(SM_CXVSCROLL);
462}
463
464
465
466//============================================================
467//  debugwin_destroy_windows
468//============================================================
469
470void debugger_windows::exit()
471{
472   // loop over windows and free them
473   while (window_list != NULL)
474   {
475      // clear the view list because they will be freed by the core
476      memset(window_list->view, 0, sizeof(window_list->view));
477      DestroyWindow(window_list->wnd);
478   }
479
480   main_console = NULL;
481}
482
483
484
485//============================================================
486//  debugger_update
487//============================================================
488
489152void debugger_windows::debugger_update()
490153{
491154   // if we're running live, do some checks
492   if (!winwindow_has_focus() && !debug_cpu_is_stopped(*m_machine) && m_machine->phase() == MACHINE_PHASE_RUNNING)
155   if (!winwindow_has_focus() && !debug_cpu_is_stopped(*m_machine) && (m_machine->phase() == MACHINE_PHASE_RUNNING))
493156   {
494157      // see if the interrupt key is pressed and break if it is
495      if (debugwin_seq_pressed(*m_machine))
158      if (seq_pressed())
496159      {
497         HWND focuswnd = GetFocus();
498         debugwin_info *info;
160         HWND const focuswnd = GetFocus();
499161
500162         debug_cpu_get_visible_cpu(*m_machine)->debug()->halt_on_next_instruction("User-initiated break\n");
501163
502164         // if we were focused on some window's edit box, reset it to default
503         for (info = window_list; info != NULL; info = info->next)
504            if (focuswnd == info->editwnd)
505            {
506               SendMessage(focuswnd, WM_SETTEXT, (WPARAM)0, (LPARAM)info->edit_defstr);
507               SendMessage(focuswnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
508            }
165         for (debugwin_info *info = m_window_list.first(); info != NULL; info = info->next())
166            info->restore_field(focuswnd);
509167      }
510168   }
511169}
512170
513171
514
515//============================================================
516//  debugwin_window_create
517//============================================================
518
519static debugwin_info *debugwin_window_create(running_machine &machine, LPCSTR title, WNDPROC handler)
172bool debugger_windows::seq_pressed() const
520173{
521   debugwin_info *info = NULL;
522   RECT work_bounds;
174   input_seq const &seq = m_machine->ioport().type_seq(IPT_UI_DEBUG_BREAK);
175   bool result = false;
176   bool invert = false;
177   bool first = true;
523178
524   // allocate memory
525   info = global_alloc_clear(debugwin_info(machine));
526
527   // create the window
528   info->handler = handler;
529   info->wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE,
530         0, 0, 100, 100, win_window_list->m_hwnd, create_standard_menubar(), GetModuleHandle(NULL), info);
531   if (info->wnd == NULL)
532      goto cleanup;
533
534   // fill in some defaults
535   SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
536   info->minwidth = 200;
537   info->minheight = 200;
538   info->maxwidth = work_bounds.right - work_bounds.left;
539   info->maxheight = work_bounds.bottom - work_bounds.top;
540
541   // set the default handlers
542   info->handle_command = global_handle_command;
543   info->handle_key = global_handle_key;
544   strcpy(info->edit_defstr, "");
545
546   // hook us in
547   info->next = window_list;
548   window_list = info;
549
550   return info;
551
552cleanup:
553   if (info->wnd != NULL)
554      DestroyWindow(info->wnd);
555   global_free(info);
556   return NULL;
557}
558
559
560
561//============================================================
562//  debugwin_window_free
563//============================================================
564
565static void debugwin_window_free(debugwin_info *info)
566{
567   debugwin_info **scanptr;
568   int viewnum;
569
570   // first unlink us from the list
571   for (scanptr = &window_list; *scanptr != NULL; scanptr = &(*scanptr)->next)
572      if (*scanptr == info)
573      {
574         *scanptr = info->next;
575         break;
576      }
577
578   // free any views
579   for (viewnum = 0; viewnum < ARRAY_LENGTH(info->view); viewnum++)
580      if (info->view[viewnum].view != NULL)
581      {
582         info->machine().debug_view().free_view(*info->view[viewnum].view);
583         info->view[viewnum].view = NULL;
584      }
585
586   // free our memory
587   global_free(info);
588}
589
590
591
592//============================================================
593//  debugwin_window_draw_contents
594//============================================================
595
596static void debugwin_window_draw_contents(debugwin_info *info, HDC dc)
597{
598   RECT bounds, parent;
599   int curview, curwnd;
600
601   // fill the background with light gray
602   GetClientRect(info->wnd, &parent);
603   FillRect(dc, &parent, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
604
605   // get the parent bounds in screen coords
606   ClientToScreen(info->wnd, &((POINT *)&parent)[0]);
607   ClientToScreen(info->wnd, &((POINT *)&parent)[1]);
608
609   // draw edges around all views
610   for (curview = 0; curview < MAX_VIEWS; curview++)
611      if (info->view[curview].wnd)
612      {
613         GetWindowRect(info->view[curview].wnd, &bounds);
614         bounds.top -= parent.top;
615         bounds.bottom -= parent.top;
616         bounds.left -= parent.left;
617         bounds.right -= parent.left;
618         InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
619         DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
620      }
621
622   // draw edges around all children
623   if (info->editwnd)
179   // iterate over all of the codes
180   for (int codenum = 0, length = seq.length(); codenum < length; codenum++)
624181   {
625      GetWindowRect(info->editwnd, &bounds);
626      bounds.top -= parent.top;
627      bounds.bottom -= parent.top;
628      bounds.left -= parent.left;
629      bounds.right -= parent.left;
630      InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
631      DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
632   }
182      input_code code = seq[codenum];
633183
634   for (curwnd = 0; curwnd < MAX_OTHER_WND; curwnd++)
635      if (info->otherwnd[curwnd])
184      if (code == input_seq::not_code)
636185      {
637         GetWindowRect(info->otherwnd[curwnd], &bounds);
638         bounds.top -= parent.top;
639         bounds.bottom -= parent.top;
640         bounds.left -= parent.left;
641         bounds.right -= parent.left;
642         InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
643         DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
186         // handle NOT
187         invert = true;
644188      }
645}
646
647
648
649//============================================================
650//  debugwin_window_proc
651//============================================================
652
653static LRESULT CALLBACK debugwin_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
654{
655   debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
656
657   // handle a few messages
658   switch (message)
659   {
660      // set the info pointer
661      case WM_CREATE:
189      else if (code == input_seq::or_code || code == input_seq::end_code)
662190      {
663         CREATESTRUCT *createinfo = (CREATESTRUCT *)lparam;
664         info = (debugwin_info *)createinfo->lpCreateParams;
665         SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
666         if (info->handler)
667            SetWindowLongPtr(wnd, GWLP_WNDPROC, (LONG_PTR)info->handler);
668         break;
669      }
191         // handle OR and END
670192
671      // paint: draw bezels as necessary
672      case WM_PAINT:
673      {
674         PAINTSTRUCT pstruct;
675         HDC dc = BeginPaint(wnd, &pstruct);
676         debugwin_window_draw_contents(info, dc);
677         EndPaint(wnd, &pstruct);
678         break;
679      }
193         // if we have a positive result from the previous set, we're done
194         if (result || code == input_seq::end_code)
195            break;
680196
681      // keydown: handle debugger keys
682      case WM_KEYDOWN:
683         if ((*info->handle_key)(info, wparam, lparam))
684            info->ignore_char_lparam = lparam >> 16;
685         break;
686
687      // char: ignore chars associated with keys we've handled
688      case WM_CHAR:
689         if (info->ignore_char_lparam == (lparam >> 16))
690            info->ignore_char_lparam = 0;
691         else if (waiting_for_debugger || !debugwin_seq_pressed(info->machine()))
692            return DefWindowProc(wnd, message, wparam, lparam);
693         break;
694
695      // activate: set the focus
696      case WM_ACTIVATE:
697         if (wparam != WA_INACTIVE && info->focuswnd != NULL)
698            SetFocus(info->focuswnd);
699         break;
700
701      // get min/max info: set the minimum window size
702      case WM_GETMINMAXINFO:
703      {
704         MINMAXINFO *minmax = (MINMAXINFO *)lparam;
705         if (info)
706         {
707            minmax->ptMinTrackSize.x = info->minwidth;
708            minmax->ptMinTrackSize.y = info->minheight;
709            minmax->ptMaxSize.x = minmax->ptMaxTrackSize.x = info->maxwidth;
710            minmax->ptMaxSize.y = minmax->ptMaxTrackSize.y = info->maxheight;
711         }
712         break;
197         // otherwise, reset our state
198         result = false;
199         invert = false;
200         first = true;
713201      }
714
715      // sizing: recompute child window locations
716      case WM_SIZE:
717      case WM_SIZING:
718         if (info->recompute_children != NULL)
719            (*info->recompute_children)(info);
720         InvalidateRect(wnd, NULL, FALSE);
721         break;
722
723      // mouse wheel: forward to the first view
724      case WM_MOUSEWHEEL:
202      else
725203      {
726         static int units_carryover = 0;
204         // handle everything else as a series of ANDs
205         int const vkey = wininput_vkey_for_mame_code(code);
206         bool const pressed = (vkey != 0) && ((GetAsyncKeyState(vkey) & 0x8000) != 0);
727207
728         UINT lines_per_click;
729         if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines_per_click, 0))
730            lines_per_click = 3;
208         if (first)         // if this is the first in the sequence, result is set equal
209            result = pressed ^ invert;
210         else if (result)   // further values are ANDed
211            result = result && (pressed ^ invert);
731212
732         int units = GET_WHEEL_DELTA_WPARAM(wparam) + units_carryover;
733         int clicks = units / WHEEL_DELTA;
734         units_carryover = units % WHEEL_DELTA;
735
736         int delta = clicks * lines_per_click;
737         int viewnum = 0;
738         POINT point;
739         HWND child;
740
741         // figure out which view we are hovering over
742         GetCursorPos(&point);
743         ScreenToClient(info->wnd, &point);
744         child = ChildWindowFromPoint(info->wnd, point);
745         if (child)
746         {
747            for (viewnum = 0; viewnum < MAX_VIEWS; viewnum++)
748               if (info->view[viewnum].wnd == child)
749                  break;
750            if (viewnum == MAX_VIEWS)
751               break;
752         }
753
754         // send the appropriate message to this view's scrollbar
755         if (info->view[viewnum].wnd && info->view[viewnum].vscroll)
756         {
757            int message_type = SB_LINEUP;
758            if (delta < 0)
759            {
760               message_type = SB_LINEDOWN;
761               delta = -delta;
762            }
763            while (delta > 0)
764            {
765               SendMessage(info->view[viewnum].wnd, WM_VSCROLL, message_type, (LPARAM)info->view[viewnum].vscroll);
766               delta--;
767            }
768         }
769         break;
213         // no longer first, and clear the invert flag
214         first = invert = false;
770215      }
771
772      // activate: set the focus
773      case WM_INITMENU:
774         if (info->update_menu != NULL)
775            (*info->update_menu)(info);
776         break;
777
778      // command: handle a comment
779      case WM_COMMAND:
780         if (!(*info->handle_command)(info, wparam, lparam))
781            return DefWindowProc(wnd, message, wparam, lparam);
782         break;
783
784      // close: close the window if it's not the main console
785      case WM_CLOSE:
786         if (main_console && main_console->wnd == wnd)
787         {
788            smart_show_all(FALSE);
789            debug_cpu_get_visible_cpu(info->machine())->debug()->go();
790         }
791         else
792            DestroyWindow(wnd);
793         break;
794
795      // destroy: close down the window
796      case WM_NCDESTROY:
797         debugwin_window_free(info);
798         break;
799
800      // everything else: defaults
801      default:
802         return DefWindowProc(wnd, message, wparam, lparam);
803216   }
804217
805   return 0;
218   // return the result if we queried at least one switch
219   return result;
806220}
807221
808222
809
810//============================================================
811//  debugwin_view_create
812//============================================================
813
814static int debugwin_view_create(debugwin_info *info, int which, debug_view_type type)
223void debugger_windows::remove_window(debugwin_info &info)
815224{
816   debugview_info *view = &info->view[which];
817
818   // set the owner
819   view->owner = info;
820
821   // create the child view
822   view->wnd = CreateWindowEx(DEBUG_VIEW_STYLE_EX, TEXT("MAMEDebugView"), NULL, DEBUG_VIEW_STYLE,
823         0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), view);
824   if (view->wnd == NULL)
825      goto cleanup;
826
827   // create the scroll bars
828   view->hscroll = CreateWindowEx(HSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, HSCROLL_STYLE,
829         0, 0, 100, CW_USEDEFAULT, view->wnd, NULL, GetModuleHandle(NULL), view);
830   view->vscroll = CreateWindowEx(VSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, VSCROLL_STYLE,
831         0, 0, CW_USEDEFAULT, 100, view->wnd, NULL, GetModuleHandle(NULL), view);
832   if (view->hscroll == NULL || view->vscroll == NULL)
833      goto cleanup;
834
835   // create the debug view
836   view->view = info->machine().debug_view().alloc_view(type, debugwin_view_update, view);
837   if (view->view == NULL)
838      goto cleanup;
839
840   return 1;
841
842cleanup:
843   if (view->view)
844      info->machine().debug_view().free_view(*view->view);
845   if (view->hscroll)
846      DestroyWindow(view->hscroll);
847   if (view->vscroll)
848      DestroyWindow(view->vscroll);
849   if (view->wnd)
850      DestroyWindow(view->wnd);
851   return 0;
225   m_window_list.remove(info);
852226}
853227
854228
855
856//============================================================
857//  debugwin_view_set_bounds
858//============================================================
859
860static void debugwin_view_set_bounds(debugview_info *info, HWND parent, const RECT *newbounds)
229void debugger_windows::show_all()
861230{
862   RECT bounds = *newbounds;
863
864   // account for the edges and set the bounds
865   if (info->wnd)
866      smart_set_window_bounds(info->wnd, parent, &bounds);
867
868   // update
869   debugwin_view_update(*info->view, info);
231   for (debugwin_info *info = m_window_list.first(); info != NULL; info = info->next())
232      info->show();
870233}
871234
872235
873
874//============================================================
875//  debugwin_view_draw_contents
876//============================================================
877
878static void debugwin_view_draw_contents(debugview_info *view, HDC windc)
236void debugger_windows::hide_all()
879237{
880   const debug_view_char *viewdata = view->view->viewdata();
881   debug_view_xy visarea = view->view->visible_size();
882   HGDIOBJ oldfont, oldbitmap;
883   COLORREF oldfgcolor;
884   UINT32 col, row;
885   HBITMAP bitmap;
886   int oldbkmode;
887   RECT client;
888   HDC dc;
889
890   // get the client rect
891   GetClientRect(view->wnd, &client);
892
893   // create a compatible DC and an offscreen bitmap
894   dc = CreateCompatibleDC(windc);
895   if (dc == NULL)
896      return;
897   bitmap = CreateCompatibleBitmap(windc, client.right, client.bottom);
898   if (bitmap == NULL)
899   {
900      DeleteDC(dc);
901      return;
902   }
903   oldbitmap = SelectObject(dc, bitmap);
904
905   // set the font
906   oldfont = SelectObject(dc, debug_font);
907   oldfgcolor = GetTextColor(dc);
908   oldbkmode = GetBkMode(dc);
909   SetBkMode(dc, TRANSPARENT);
910
911   // iterate over rows and columns
912   for (row = 0; row < visarea.y; row++)
913   {
914      int iter;
915
916      // loop twice; once to fill the background and once to draw the text
917      for (iter = 0; iter < 2; iter++)
918      {
919         COLORREF fgcolor = RGB(0x00,0x00,0x00);
920         COLORREF bgcolor = RGB(0xff,0xff,0xff);
921         HBRUSH bgbrush = NULL;
922         int last_attrib = -1;
923         TCHAR buffer[256];
924         int count = 0;
925         RECT bounds;
926
927         // initialize the text bounds
928         bounds.left = bounds.right = 0;
929         bounds.top = row * debug_font_height;
930         bounds.bottom = bounds.top + debug_font_height;
931
932         // start with a brush on iteration #0
933         if (iter == 0)
934            bgbrush = CreateSolidBrush(bgcolor);
935
936         // iterate over columns
937         for (col = 0; col < visarea.x; col++)
938         {
939            // if the attribute changed, adjust the colors
940            if (viewdata[col].attrib != last_attrib)
941            {
942               COLORREF oldbg = bgcolor;
943
944               // reset to standard colors
945               fgcolor = RGB(0x00,0x00,0x00);
946               bgcolor = RGB(0xff,0xff,0xff);
947
948               // pick new fg/bg colors
949               if (viewdata[col].attrib & DCA_ANCILLARY) bgcolor = RGB(0xe0,0xe0,0xe0);
950               if (viewdata[col].attrib & DCA_SELECTED) bgcolor = RGB(0xff,0x80,0x80);
951               if (viewdata[col].attrib & DCA_CURRENT) bgcolor = RGB(0xff,0xff,0x00);
952               if ((viewdata[col].attrib & DCA_SELECTED) && (viewdata[col].attrib & DCA_CURRENT)) bgcolor = RGB(0xff,0xc0,0x80);
953               if (viewdata[col].attrib & DCA_CHANGED) fgcolor = RGB(0xff,0x00,0x00);
954               if (viewdata[col].attrib & DCA_INVALID) fgcolor = RGB(0x00,0x00,0xff);
955               if (viewdata[col].attrib & DCA_DISABLED) fgcolor = RGB((GetRValue(fgcolor) + GetRValue(bgcolor)) / 2, (GetGValue(fgcolor) + GetGValue(bgcolor)) / 2, (GetBValue(fgcolor) + GetBValue(bgcolor)) / 2);
956               if (viewdata[col].attrib & DCA_COMMENT) fgcolor = RGB(0x00,0x80,0x00);
957
958               // flush any pending drawing
959               if (count > 0)
960               {
961                  bounds.right = bounds.left + count * debug_font_width;
962                  if (iter == 0)
963                     FillRect(dc, &bounds, bgbrush);
964                  else
965                     ExtTextOut(dc, bounds.left, bounds.top, 0, NULL, buffer, count, NULL);
966                  bounds.left = bounds.right;
967                  count = 0;
968               }
969
970               // set the new colors
971               if (iter == 0 && oldbg != bgcolor)
972               {
973                  DeleteObject(bgbrush);
974                  bgbrush = CreateSolidBrush(bgcolor);
975               }
976               else if (iter == 1)
977                  SetTextColor(dc, fgcolor);
978               last_attrib = viewdata[col].attrib;
979            }
980
981            // add this character to the buffer
982            buffer[count++] = viewdata[col].byte;
983         }
984
985         // flush any remaining stuff
986         if (count > 0)
987         {
988            bounds.right = bounds.left + count * debug_font_width;
989            if (iter == 0)
990               FillRect(dc, &bounds, bgbrush);
991            else
992               ExtTextOut(dc, bounds.left, bounds.top, 0, NULL, buffer, count, NULL);
993         }
994
995         // erase to the end of the line
996         if (iter == 0)
997         {
998            bounds.left = bounds.right;
999            bounds.right = client.right;
1000            FillRect(dc, &bounds, bgbrush);
1001            DeleteObject(bgbrush);
1002         }
1003      }
1004
1005      // advance viewdata
1006      viewdata += visarea.x;
1007   }
1008
1009   // erase anything beyond the bottom with white
1010   GetClientRect(view->wnd, &client);
1011   client.top = visarea.y * debug_font_height;
1012   FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH));
1013
1014   // reset the font
1015   SetBkMode(dc, oldbkmode);
1016   SetTextColor(dc, oldfgcolor);
1017   SelectObject(dc, oldfont);
1018
1019   // blit the final results
1020   BitBlt(windc, 0, 0, client.right, client.bottom, dc, 0, 0, SRCCOPY);
1021
1022   // undo the offscreen stuff
1023   SelectObject(dc, oldbitmap);
1024   DeleteObject(bitmap);
1025   DeleteDC(dc);
238   SetForegroundWindow(win_window_list->m_hwnd);
239   for (debugwin_info *info = m_window_list.first(); info != NULL; info = info->next())
240      info->hide();
1026241}
1027242
1028243
1029
1030//============================================================
1031//  debugwin_view_update
1032//============================================================
1033
1034static void debugwin_view_update(debug_view &view, void *osdprivate)
244template <typename T> T *debugger_windows::create_window()
1035245{
1036   debugview_info *info = (debugview_info *)osdprivate;
1037   RECT bounds, vscroll_bounds, hscroll_bounds;
1038   debug_view_xy totalsize, visiblesize, topleft;
1039   int show_vscroll, show_hscroll;
1040   SCROLLINFO scrollinfo;
1041
1042   assert(info->view == &view);
1043
1044   // get the view window bounds
1045   GetClientRect(info->wnd, &bounds);
1046   visiblesize.x = (bounds.right - bounds.left) / debug_font_width;
1047   visiblesize.y = (bounds.bottom - bounds.top) / debug_font_height;
1048
1049   // get the updated total rows/cols and left row/col
1050   totalsize = view.total_size();
1051   topleft = view.visible_position();
1052
1053   // determine if we need to show the scrollbars
1054   show_vscroll = show_hscroll = FALSE;
1055   if (totalsize.x > visiblesize.x && bounds.bottom >= hscroll_height)
246   // allocate memory
247   T *info = global_alloc(T(*this));
248   if (info->is_valid())
1056249   {
1057      bounds.bottom -= hscroll_height;
1058      visiblesize.y = (bounds.bottom - bounds.top) / debug_font_height;
1059      show_hscroll = TRUE;
250      m_window_list.prepend(*info);
251      return info;
1060252   }
1061   if (totalsize.y > visiblesize.y && bounds.right >= vscroll_width)
1062   {
1063      bounds.right -= vscroll_width;
1064      visiblesize.x = (bounds.right - bounds.left) / debug_font_width;
1065      show_vscroll = TRUE;
1066   }
1067   if (!show_vscroll && totalsize.y > visiblesize.y && bounds.right >= vscroll_width)
1068   {
1069      bounds.right -= vscroll_width;
1070      visiblesize.x = (bounds.right - bounds.left) / debug_font_width;
1071      show_vscroll = TRUE;
1072   }
1073
1074   // compute the bounds of the scrollbars
1075   GetClientRect(info->wnd, &vscroll_bounds);
1076   vscroll_bounds.left = vscroll_bounds.right - vscroll_width;
1077   if (show_hscroll)
1078      vscroll_bounds.bottom -= hscroll_height;
1079
1080   GetClientRect(info->wnd, &hscroll_bounds);
1081   hscroll_bounds.top = hscroll_bounds.bottom - hscroll_height;
1082   if (show_vscroll)
1083      hscroll_bounds.right -= vscroll_width;
1084
1085   // if we hid the scrollbars, make sure we reset the top/left corners
1086   if (topleft.y + visiblesize.y > totalsize.y)
1087      topleft.y = MAX(totalsize.y - visiblesize.y, 0);
1088   if (topleft.x + visiblesize.x > totalsize.x)
1089      topleft.x = MAX(totalsize.x - visiblesize.x, 0);
1090
1091   // fill out the scroll info struct for the vertical scrollbar
1092   scrollinfo.cbSize = sizeof(scrollinfo);
1093   scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
1094   scrollinfo.nMin = 0;
1095   scrollinfo.nMax = totalsize.y - 1;
1096   scrollinfo.nPage = visiblesize.y;
1097   scrollinfo.nPos = topleft.y;
1098   SetScrollInfo(info->vscroll, SB_CTL, &scrollinfo, TRUE);
1099
1100   // fill out the scroll info struct for the horizontal scrollbar
1101   scrollinfo.cbSize = sizeof(scrollinfo);
1102   scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
1103   scrollinfo.nMin = 0;
1104   scrollinfo.nMax = totalsize.x - 1;
1105   scrollinfo.nPage = visiblesize.x;
1106   scrollinfo.nPos = topleft.x;
1107   SetScrollInfo(info->hscroll, SB_CTL, &scrollinfo, TRUE);
1108
1109   // update window info
1110   visiblesize.y++;
1111   visiblesize.x++;
1112   view.set_visible_size(visiblesize);
1113   view.set_visible_position(topleft);
1114
1115   // invalidate the bounds
1116   InvalidateRect(info->wnd, NULL, FALSE);
1117
1118   // adjust the bounds of the scrollbars and show/hide them
1119   if (info->vscroll)
1120   {
1121      if (show_vscroll)
1122         smart_set_window_bounds(info->vscroll, info->wnd, &vscroll_bounds);
1123      smart_show_window(info->vscroll, show_vscroll);
1124   }
1125   if (info->hscroll)
1126   {
1127      if (show_hscroll)
1128         smart_set_window_bounds(info->hscroll, info->wnd, &hscroll_bounds);
1129      smart_show_window(info->hscroll, show_hscroll);
1130   }
1131}
1132
1133
1134
1135//============================================================
1136//  debugwin_view_process_scroll
1137//============================================================
1138
1139static UINT32 debugwin_view_process_scroll(debugview_info *info, WORD type, HWND wnd)
1140{
1141   SCROLLINFO scrollinfo;
1142   INT32 maxval;
1143   INT32 result;
1144
1145   // get the current info
1146   scrollinfo.cbSize = sizeof(scrollinfo);
1147   scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
1148   GetScrollInfo(wnd, SB_CTL, &scrollinfo);
1149
1150   // by default we stay put
1151   result = scrollinfo.nPos;
1152
1153   // determine the maximum value
1154   maxval = (scrollinfo.nMax > scrollinfo.nPage) ? (scrollinfo.nMax - scrollinfo.nPage + 1) : 0;
1155
1156   // handle the message
1157   switch (type)
1158   {
1159      case SB_THUMBTRACK:
1160         result = scrollinfo.nTrackPos;
1161         break;
1162
1163      case SB_LEFT:
1164         result = 0;
1165         break;
1166
1167      case SB_RIGHT:
1168         result = maxval;
1169         break;
1170
1171      case SB_LINELEFT:
1172         result -= 1;
1173         break;
1174
1175      case SB_LINERIGHT:
1176         result += 1;
1177         break;
1178
1179      case SB_PAGELEFT:
1180         result -= scrollinfo.nPage - 1;
1181         break;
1182
1183      case SB_PAGERIGHT:
1184         result += scrollinfo.nPage - 1;
1185         break;
1186   }
1187
1188   // generic rangecheck
1189   if (result < 0)
1190      result = 0;
1191   if (result > maxval)
1192      result = maxval;
1193
1194   // set the new position
1195   scrollinfo.fMask = SIF_POS;
1196   scrollinfo.nPos = result;
1197   SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE);
1198
1199   return (UINT32)result;
1200}
1201
1202
1203
1204//============================================================
1205//  debugwin_view_prev_view
1206//============================================================
1207
1208static void debugwin_view_prev_view(debugwin_info *info, debugview_info *curview)
1209{
1210   int curindex = 1;
1211   int numviews;
1212
1213   // count the number of views
1214   for (numviews = 0; numviews < MAX_VIEWS; numviews++)
1215      if (info->view[numviews].wnd == NULL)
1216         break;
1217
1218   // if we have a curview, find out its index
1219   if (curview)
1220      curindex = curview - &info->view[0];
1221
1222   // loop until we find someone to take focus
1223   while (1)
1224   {
1225      // advance to the previous index
1226      curindex--;
1227      if (curindex < -1)
1228         curindex = numviews - 1;
1229
1230      // negative numbers mean the focuswnd
1231      if (curindex < 0 && info->focuswnd != NULL)
1232      {
1233         SetFocus(info->focuswnd);
1234         break;
1235      }
1236
1237      // positive numbers mean a view
1238      else if (curindex >= 0 && info->view[curindex].wnd != NULL && info->view[curindex].view->cursor_supported())
1239      {
1240         SetFocus(info->view[curindex].wnd);
1241         break;
1242      }
1243   }
1244}
1245
1246
1247
1248//============================================================
1249//  debugwin_view_next_view
1250//============================================================
1251
1252static void debugwin_view_next_view(debugwin_info *info, debugview_info *curview)
1253{
1254   int curindex = -1;
1255   int numviews;
1256
1257   // count the number of views
1258   for (numviews = 0; numviews < MAX_VIEWS; numviews++)
1259      if (info->view[numviews].wnd == NULL)
1260         break;
1261
1262   // if we have a curview, find out its index
1263   if (curview)
1264      curindex = curview - &info->view[0];
1265
1266   // loop until we find someone to take focus
1267   while (1)
1268   {
1269      // advance to the previous index
1270      curindex++;
1271      if (curindex >= numviews)
1272         curindex = -1;
1273
1274      // negative numbers mean the focuswnd
1275      if (curindex < 0 && info->focuswnd != NULL)
1276      {
1277         SetFocus(info->focuswnd);
1278         break;
1279      }
1280
1281      // positive numbers mean a view
1282      else if (curindex >= 0 && info->view[curindex].wnd != NULL && info->view[curindex].view->cursor_supported())
1283      {
1284         SetFocus(info->view[curindex].wnd);
1285         InvalidateRect(info->view[curindex].wnd, NULL, FALSE);
1286         break;
1287      }
1288   }
1289}
1290
1291
1292
1293//============================================================
1294//  debugwin_view_proc
1295//============================================================
1296
1297static LRESULT CALLBACK debugwin_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1298{
1299   debugview_info *info = (debugview_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
1300
1301   // handle a few messages
1302   switch (message)
1303   {
1304      // set the info pointer
1305      case WM_CREATE:
1306      {
1307         CREATESTRUCT *createinfo = (CREATESTRUCT *)lparam;
1308         SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
1309         break;
1310      }
1311
1312      // paint: redraw the last bitmap
1313      case WM_PAINT:
1314      {
1315         PAINTSTRUCT pstruct;
1316         HDC dc = BeginPaint(wnd, &pstruct);
1317         debugwin_view_draw_contents(info, dc);
1318         EndPaint(wnd, &pstruct);
1319         break;
1320      }
1321
1322      // keydown: handle debugger keys
1323      case WM_SYSKEYDOWN:
1324         if (wparam != VK_F10)
1325            return DefWindowProc(wnd, message, wparam, lparam);
1326         // (fall through)
1327      case WM_KEYDOWN:
1328      {
1329         if ((*info->owner->handle_key)(info->owner, wparam, lparam))
1330            info->owner->ignore_char_lparam = lparam >> 16;
1331         else
1332         {
1333            switch (wparam)
1334            {
1335               case VK_UP:
1336                  info->view->process_char(DCH_UP);
1337                  info->owner->ignore_char_lparam = lparam >> 16;
1338                  break;
1339
1340               case VK_DOWN:
1341                  info->view->process_char(DCH_DOWN);
1342                  info->owner->ignore_char_lparam = lparam >> 16;
1343                  break;
1344
1345               case VK_LEFT:
1346                  if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1347                     info->view->process_char(DCH_CTRLLEFT);
1348                  else
1349                     info->view->process_char(DCH_LEFT);
1350                  info->owner->ignore_char_lparam = lparam >> 16;
1351                  break;
1352
1353               case VK_RIGHT:
1354                  if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1355                     info->view->process_char(DCH_CTRLRIGHT);
1356                  else
1357                     info->view->process_char(DCH_RIGHT);
1358                  info->owner->ignore_char_lparam = lparam >> 16;
1359                  break;
1360
1361               case VK_PRIOR:
1362                  info->view->process_char(DCH_PUP);
1363                  info->owner->ignore_char_lparam = lparam >> 16;
1364                  break;
1365
1366               case VK_NEXT:
1367                  info->view->process_char(DCH_PDOWN);
1368                  info->owner->ignore_char_lparam = lparam >> 16;
1369                  break;
1370
1371               case VK_HOME:
1372                  if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1373                     info->view->process_char(DCH_CTRLHOME);
1374                  else
1375                     info->view->process_char(DCH_HOME);
1376                  info->owner->ignore_char_lparam = lparam >> 16;
1377                  break;
1378
1379               case VK_END:
1380                  if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1381                     info->view->process_char(DCH_CTRLEND);
1382                  else
1383                     info->view->process_char(DCH_END);
1384                  info->owner->ignore_char_lparam = lparam >> 16;
1385                  break;
1386
1387               case VK_ESCAPE:
1388                  if (info->owner->focuswnd != NULL)
1389                     SetFocus(info->owner->focuswnd);
1390                  info->owner->ignore_char_lparam = lparam >> 16;
1391                  break;
1392
1393               case VK_TAB:
1394                  if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
1395                     debugwin_view_prev_view(info->owner, info);
1396                  else
1397                     debugwin_view_next_view(info->owner, info);
1398                  info->owner->ignore_char_lparam = lparam >> 16;
1399                  break;
1400            }
1401         }
1402         break;
1403      }
1404
1405      // char: ignore chars associated with keys we've handled
1406      case WM_CHAR:
1407      {
1408         if (info->owner->ignore_char_lparam == (lparam >> 16))
1409            info->owner->ignore_char_lparam = 0;
1410         else if (waiting_for_debugger || !debugwin_seq_pressed(info->owner->machine()))
1411         {
1412            if (wparam >= 32 && wparam < 127 && info->view->cursor_supported())
1413               info->view->process_char(wparam);
1414            else
1415               return DefWindowProc(wnd, message, wparam, lparam);
1416         }
1417         break;
1418      }
1419
1420      // gaining focus
1421      case WM_SETFOCUS:
1422      {
1423         if (info->view->cursor_supported())
1424            info->view->set_cursor_visible(true);
1425         break;
1426      }
1427
1428      // losing focus
1429      case WM_KILLFOCUS:
1430      {
1431         if (info->view->cursor_supported())
1432            info->view->set_cursor_visible(false);
1433         break;
1434      }
1435
1436      // mouse click
1437      case WM_LBUTTONDOWN:
1438      {
1439         if (info->view->cursor_supported())
1440         {
1441            debug_view_xy topleft = info->view->visible_position();
1442            debug_view_xy newpos;
1443            newpos.x = topleft.x + GET_X_LPARAM(lparam) / debug_font_width;
1444            newpos.y = topleft.y + GET_Y_LPARAM(lparam) / debug_font_height;
1445            info->view->set_cursor_position(newpos);
1446            SetFocus(wnd);
1447         }
1448         break;
1449      }
1450
1451      // hscroll
1452      case WM_HSCROLL:
1453      {
1454         debug_view_xy topleft = info->view->visible_position();
1455         topleft.x = debugwin_view_process_scroll(info, LOWORD(wparam), (HWND)lparam);
1456         info->view->set_visible_position(topleft);
1457         info->owner->machine().debug_view().flush_osd_updates();
1458         break;
1459      }
1460
1461      // vscroll
1462      case WM_VSCROLL:
1463      {
1464         debug_view_xy topleft = info->view->visible_position();
1465         topleft.y = debugwin_view_process_scroll(info, LOWORD(wparam), (HWND)lparam);
1466         info->view->set_visible_position(topleft);
1467         info->owner->machine().debug_view().flush_osd_updates();
1468         break;
1469      }
1470
1471      // everything else: defaults
1472      default:
1473         return DefWindowProc(wnd, message, wparam, lparam);
1474   }
1475
1476   return 0;
1477}
1478
1479
1480
1481//============================================================
1482//  debugwin_edit_proc
1483//============================================================
1484
1485static LRESULT CALLBACK debugwin_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
1486{
1487   debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
1488   TCHAR buffer[MAX_EDIT_STRING];
1489
1490   // handle a few messages
1491   switch (message)
1492   {
1493      // key down: handle navigation in the attached view
1494      case WM_SYSKEYDOWN:
1495         if (wparam != VK_F10)
1496            return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
1497         // (fall through)
1498      case WM_KEYDOWN:
1499         switch (wparam)
1500         {
1501            case VK_UP:
1502               if (info->last_history < info->history_count - 1)
1503                  info->last_history++;
1504               else
1505                  info->last_history = 0;
1506               SendMessage(wnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&info->history[info->last_history][0]);
1507               SendMessage(wnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
1508               break;
1509
1510            case VK_DOWN:
1511               if (info->last_history > 0)
1512                  info->last_history--;
1513               else if (info->history_count > 0)
1514                  info->last_history = info->history_count - 1;
1515               else
1516                  info->last_history = 0;
1517               SendMessage(wnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&info->history[info->last_history][0]);
1518               SendMessage(wnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
1519               break;
1520
1521            case VK_PRIOR:
1522               if (info->view[0].wnd && info->view[0].vscroll)
1523                  SendMessage(info->view[0].wnd, WM_VSCROLL, SB_PAGELEFT, (LPARAM)info->view[0].vscroll);
1524               break;
1525
1526            case VK_NEXT:
1527               if (info->view[0].wnd && info->view[0].vscroll)
1528                  SendMessage(info->view[0].wnd, WM_VSCROLL, SB_PAGERIGHT, (LPARAM)info->view[0].vscroll);
1529               break;
1530
1531            case VK_TAB:
1532               if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
1533                  debugwin_view_prev_view(info, NULL);
1534               else
1535                  debugwin_view_next_view(info, NULL);
1536               info->ignore_char_lparam = lparam >> 16;
1537               break;
1538
1539            default:
1540               if ((*info->handle_key)(info, wparam, lparam))
1541                  info->ignore_char_lparam = lparam >> 16;
1542               else
1543                  return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
1544               break;
1545         }
1546         break;
1547
1548      // char: handle the return key
1549      case WM_CHAR:
1550
1551         // ignore chars associated with keys we've handled
1552         if (info->ignore_char_lparam == (lparam >> 16))
1553            info->ignore_char_lparam = 0;
1554         else if (waiting_for_debugger || !debugwin_seq_pressed(info->machine()))
1555         {
1556            switch (wparam)
1557            {
1558               case 13:
1559               {
1560                  // fetch the text
1561                  SendMessage(wnd, WM_GETTEXT, (WPARAM)ARRAY_LENGTH(buffer), (LPARAM)buffer);
1562
1563                  // add to the history if it's not a repeat of the last one
1564                  if (buffer[0] != 0 && _tcscmp(buffer, &info->history[0][0]))
1565                  {
1566                     memmove(&info->history[1][0], &info->history[0][0], (HISTORY_LENGTH - 1) * MAX_EDIT_STRING);
1567                     _tcscpy(&info->history[0][0], buffer);
1568                     if (info->history_count < HISTORY_LENGTH)
1569                        info->history_count++;
1570                  }
1571                  info->last_history = info->history_count - 1;
1572
1573                  // process
1574                  if (info->process_string)
1575                  {
1576                     char *utf8_buffer = utf8_from_tstring(buffer);
1577                     if (utf8_buffer != NULL)
1578                     {
1579                        (*info->process_string)(info, utf8_buffer);
1580                        osd_free(utf8_buffer);
1581                     }
1582                  }
1583                  break;
1584               }
1585
1586               case 27:
1587               {
1588                  // fetch the text
1589                  SendMessage(wnd, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer);
1590
1591                  // if it's not empty, clear the text
1592                  if (_tcslen(buffer) > 0)
1593                  {
1594                     info->ignore_char_lparam = lparam >> 16;
1595                     SendMessage(wnd, WM_SETTEXT, (WPARAM)0, (LPARAM)info->edit_defstr);
1596                  }
1597                  break;
1598               }
1599
1600               default:
1601                  return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
1602            }
1603         }
1604         break;
1605
1606      // everything else: defaults
1607      default:
1608         return CallWindowProc(info->original_editproc, wnd, message, wparam, lparam);
1609   }
1610
1611   return 0;
1612}
1613
1614
1615
1616//============================================================
1617//  generic_create_window
1618//============================================================
1619
1620#ifdef UNUSED_FUNCTION
1621static void generic_create_window(running_machine &machine, debug_view_type type)
1622{
1623   debugwin_info *info;
1624   char title[256];
1625
1626   // create the window
1627   _snprintf(title, ARRAY_LENGTH(title), "Debug: %s [%s]", machine.system().description, machine.system().name);
1628   info = debugwin_window_create(machine, title, NULL);
1629   if (info == NULL || !debugwin_view_create(info, 0, type))
1630      return;
1631
1632   // set the child function
1633   info->recompute_children = generic_recompute_children;
1634
1635   // recompute the children once to get the maxwidth
1636   generic_recompute_children(info);
1637
1638   // position the window and recompute children again
1639   SetWindowPos(info->wnd, HWND_TOP, 100, 100, info->maxwidth, 200, SWP_SHOWWINDOW);
1640   generic_recompute_children(info);
1641}
1642#endif
1643
1644
1645
1646//============================================================
1647//  generic_recompute_children
1648//============================================================
1649
1650static void generic_recompute_children(debugwin_info *info)
1651{
1652   debug_view_xy totalsize = info->view[0].view->total_size();
1653   RECT parent;
1654   RECT bounds;
1655
1656   // compute a client rect
1657   bounds.top = bounds.left = 0;
1658   bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
1659   bounds.bottom = 200;
1660   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
1661
1662   // clamp the min/max size
1663   info->maxwidth = bounds.right - bounds.left;
1664
1665   // get the parent's dimensions
1666   GetClientRect(info->wnd, &parent);
1667
1668   // view gets the remaining space
1669   InflateRect(&parent, -EDGE_WIDTH, -EDGE_WIDTH);
1670   debugwin_view_set_bounds(&info->view[0], info->wnd, &parent);
1671}
1672
1673
1674
1675//============================================================
1676//  log_create_window
1677//============================================================
1678
1679static void log_create_window(running_machine &machine)
1680{
1681   debug_view_xy totalsize;
1682   debugwin_info *info;
1683   char title[256];
1684   RECT bounds;
1685
1686   // create the window
1687   _snprintf(title, ARRAY_LENGTH(title), "Errorlog: %s [%s]", machine.system().description, machine.system().name);
1688   info = debugwin_window_create(machine, title, NULL);
1689   if (info == NULL || !debugwin_view_create(info, 0, DVT_LOG))
1690      return;
1691
1692   // set the child function
1693   info->recompute_children = generic_recompute_children;
1694
1695   // get the view width
1696   totalsize = info->view[0].view->total_size();
1697
1698   // compute a client rect
1699   bounds.top = bounds.left = 0;
1700   bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
1701   bounds.bottom = 200;
1702   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
1703
1704   // clamp the min/max size
1705   info->maxwidth = bounds.right - bounds.left;
1706
1707   // position the window at the bottom-right
1708   SetWindowPos(info->wnd, HWND_TOP,
1709            100, 100,
1710            bounds.right - bounds.left, bounds.bottom - bounds.top,
1711            SWP_SHOWWINDOW);
1712
1713   // recompute the children and set focus on the edit box
1714   generic_recompute_children(info);
1715}
1716
1717
1718
1719//============================================================
1720//  memory_create_window
1721//============================================================
1722
1723static void memory_create_window(running_machine &machine)
1724{
1725   device_t *curcpu = debug_cpu_get_visible_cpu(machine);
1726   debugwin_info *info;
1727   HMENU optionsmenu;
1728
1729   // create the window
1730   info = debugwin_window_create(machine, "Memory", NULL);
1731   if (info == NULL || !debugwin_view_create(info, 0, DVT_MEMORY))
1732      return;
1733
1734   // set the handlers
1735   info->handle_command = memory_handle_command;
1736   info->handle_key = memory_handle_key;
1737   info->update_menu = memory_update_menu;
1738
1739   // create the options menu
1740   optionsmenu = CreatePopupMenu();
1741   AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS, TEXT("1-byte chunks\tCtrl+1"));
1742   AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS, TEXT("2-byte chunks\tCtrl+2"));
1743   AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS, TEXT("4-byte chunks\tCtrl+4"));
1744   AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS, TEXT("8-byte chunks\tCtrl+8"));
1745   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
1746   AppendMenu(optionsmenu, MF_ENABLED, ID_LOGICAL_ADDRESSES, TEXT("Logical Addresses\tCtrl+L"));
1747   AppendMenu(optionsmenu, MF_ENABLED, ID_PHYSICAL_ADDRESSES, TEXT("Physical Addresses\tCtrl+Y"));
1748   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
1749   AppendMenu(optionsmenu, MF_ENABLED, ID_REVERSE_VIEW, TEXT("Reverse View\tCtrl+R"));
1750   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
1751   AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase bytes per line\tCtrl+P"));
1752   AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease bytes per line\tCtrl+O"));
1753   AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
1754
1755   // set up the view to track the initial expression
1756   downcast<debug_view_memory *>(info->view[0].view)->set_expression("0");
1757   strcpy(info->edit_defstr, "0");
1758
1759   // create an edit box and override its key handling
1760   info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
1761         0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL);
1762   info->original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC);
1763   SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info);
1764   SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc);
1765   SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
1766   SendMessage(info->editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("0"));
1767   SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
1768   SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
1769
1770   // create a combo box
1771   info->otherwnd[0] = CreateWindowEx(COMBO_BOX_STYLE_EX, TEXT("COMBOBOX"), NULL, COMBO_BOX_STYLE,
1772         0, 0, 100, 1000, info->wnd, NULL, GetModuleHandle(NULL), NULL);
1773   SetWindowLongPtr(info->otherwnd[0], GWLP_USERDATA, (LONG_PTR)info);
1774   SendMessage(info->otherwnd[0], WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
1775
1776   // populate the combobox
1777   int maxlength = 0;
1778   for (const debug_view_source *source = info->view[0].view->first_source(); source != NULL; source = source->next())
1779   {
1780      int length = strlen(source->name());
1781      if (length > maxlength)
1782         maxlength = length;
1783      TCHAR *t_name = tstring_from_utf8(source->name());
1784      SendMessage(info->otherwnd[0], CB_ADDSTRING, 0, (LPARAM)t_name);
1785      osd_free(t_name);
1786   }
1787   const debug_view_source *source = info->view[0].view->source_for_device(curcpu);
1788   SendMessage(info->otherwnd[0], CB_SETCURSEL, info->view[0].view->source_list().indexof(*source), 0);
1789   SendMessage(info->otherwnd[0], CB_SETDROPPEDWIDTH, (maxlength + 2) * debug_font_width + vscroll_width, 0);
1790   info->view[0].view->set_source(*source);
1791
1792   // set the child functions
1793   info->recompute_children = memory_recompute_children;
1794   info->process_string = memory_process_string;
1795
1796   // set the caption
1797   memory_update_caption(machine, info->wnd);
1798
1799   // recompute the children once to get the maxwidth
1800   memory_recompute_children(info);
1801
1802   // position the window and recompute children again
1803   SetWindowPos(info->wnd, HWND_TOP, 100, 100, info->maxwidth, 200, SWP_SHOWWINDOW);
1804   memory_recompute_children(info);
1805
1806   // mark the edit box as the default focus and set it
1807   info->focuswnd = info->editwnd;
1808   SetFocus(info->editwnd);
1809}
1810
1811
1812
1813//============================================================
1814//  memory_recompute_children
1815//============================================================
1816
1817static void memory_recompute_children(debugwin_info *info)
1818{
1819   debug_view_xy totalsize = info->view[0].view->total_size();
1820   RECT parent, memrect, editrect, comborect;
1821   RECT bounds;
1822
1823   // compute a client rect
1824   bounds.top = bounds.left = 0;
1825   bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
1826   bounds.bottom = 200;
1827   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
1828
1829   // clamp the min/max size
1830   info->maxwidth = bounds.right - bounds.left;
1831
1832   // get the parent's dimensions
1833   GetClientRect(info->wnd, &parent);
1834
1835   // edit box gets half of the width
1836   editrect.top = parent.top + EDGE_WIDTH;
1837   editrect.bottom = editrect.top + debug_font_height + 4;
1838   editrect.left = parent.left + EDGE_WIDTH;
1839   editrect.right = parent.left + (parent.right - parent.left) / 2 - EDGE_WIDTH;
1840
1841   // combo box gets the other half of the width
1842   comborect.top = editrect.top;
1843   comborect.bottom = editrect.bottom;
1844   comborect.left = editrect.right + 2 * EDGE_WIDTH;
1845   comborect.right = parent.right - EDGE_WIDTH;
1846
1847   // memory view gets the rest
1848   memrect.top = editrect.bottom + 2 * EDGE_WIDTH;
1849   memrect.bottom = parent.bottom - EDGE_WIDTH;
1850   memrect.left = parent.left + EDGE_WIDTH;
1851   memrect.right = parent.right - EDGE_WIDTH;
1852
1853   // set the bounds of things
1854   debugwin_view_set_bounds(&info->view[0], info->wnd, &memrect);
1855   smart_set_window_bounds(info->editwnd, info->wnd, &editrect);
1856   smart_set_window_bounds(info->otherwnd[0], info->wnd, &comborect);
1857}
1858
1859
1860
1861//============================================================
1862//  memory_process_string
1863//============================================================
1864
1865static void memory_process_string(debugwin_info *info, const char *string)
1866{
1867   // set the string to the memory view
1868   downcast<debug_view_memory *>(info->view[0].view)->set_expression(string);
1869
1870   // select everything in the edit text box
1871   SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
1872
1873   // update the default string to match
1874   strncpy(info->edit_defstr, string, sizeof(info->edit_defstr) - 1);
1875}
1876
1877
1878
1879//============================================================
1880//  memory_update_menu
1881//============================================================
1882
1883static void memory_update_menu(debugwin_info *info)
1884{
1885   debug_view_memory *memview = downcast<debug_view_memory *>(info->view[0].view);
1886   CheckMenuItem(GetMenu(info->wnd), ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 1 ? MF_CHECKED : MF_UNCHECKED));
1887   CheckMenuItem(GetMenu(info->wnd), ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 2 ? MF_CHECKED : MF_UNCHECKED));
1888   CheckMenuItem(GetMenu(info->wnd), ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 4 ? MF_CHECKED : MF_UNCHECKED));
1889   CheckMenuItem(GetMenu(info->wnd), ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 8 ? MF_CHECKED : MF_UNCHECKED));
1890   CheckMenuItem(GetMenu(info->wnd), ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED));
1891   CheckMenuItem(GetMenu(info->wnd), ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED));
1892   CheckMenuItem(GetMenu(info->wnd), ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED));
1893}
1894
1895
1896
1897//============================================================
1898//  memory_handle_command
1899//============================================================
1900
1901static int memory_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam)
1902{
1903   debug_view_memory *memview = downcast<debug_view_memory *>(info->view[0].view);
1904   switch (HIWORD(wparam))
1905   {
1906      // combo box selection changed
1907      case CBN_SELCHANGE:
1908      {
1909         int sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
1910         if (sel != CB_ERR)
1911         {
1912            memview->set_source(*memview->source_list().find(sel));
1913            memory_update_caption(info->machine(), info->wnd);
1914
1915            // reset the focus
1916            SetFocus(info->focuswnd);
1917            return 1;
1918         }
1919         break;
1920      }
1921
1922      // menu selections
1923      case 0:
1924         switch (LOWORD(wparam))
1925         {
1926            case ID_1_BYTE_CHUNKS:
1927               memview->set_bytes_per_chunk(1);
1928               return 1;
1929
1930            case ID_2_BYTE_CHUNKS:
1931               memview->set_bytes_per_chunk(2);
1932               return 1;
1933
1934            case ID_4_BYTE_CHUNKS:
1935               memview->set_bytes_per_chunk(4);
1936               return 1;
1937
1938            case ID_8_BYTE_CHUNKS:
1939               memview->set_bytes_per_chunk(8);
1940               return 1;
1941
1942            case ID_LOGICAL_ADDRESSES:
1943               memview->set_physical(false);
1944               return 1;
1945
1946            case ID_PHYSICAL_ADDRESSES:
1947               memview->set_physical(true);
1948               return 1;
1949
1950            case ID_REVERSE_VIEW:
1951               memview->set_reverse(!memview->reverse());
1952               return 1;
1953
1954            case ID_INCREASE_MEM_WIDTH:
1955               memview->set_chunks_per_row(memview->chunks_per_row() + 1);
1956               return 1;
1957
1958            case ID_DECREASE_MEM_WIDTH:
1959               memview->set_chunks_per_row(memview->chunks_per_row() - 1);
1960               return 1;
1961         }
1962         break;
1963   }
1964   return global_handle_command(info, wparam, lparam);
1965}
1966
1967
1968
1969//============================================================
1970//  memory_handle_key
1971//============================================================
1972
1973static int memory_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam)
1974{
1975   if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1976   {
1977      switch (wparam)
1978      {
1979         case '1':
1980            SendMessage(info->wnd, WM_COMMAND, ID_1_BYTE_CHUNKS, 0);
1981            return 1;
1982
1983         case '2':
1984            SendMessage(info->wnd, WM_COMMAND, ID_2_BYTE_CHUNKS, 0);
1985            return 1;
1986
1987         case '4':
1988            SendMessage(info->wnd, WM_COMMAND, ID_4_BYTE_CHUNKS, 0);
1989            return 1;
1990
1991         case '8':
1992            SendMessage(info->wnd, WM_COMMAND, ID_8_BYTE_CHUNKS, 0);
1993            return 1;
1994
1995         case 'L':
1996            SendMessage(info->wnd, WM_COMMAND, ID_LOGICAL_ADDRESSES, 0);
1997            return 1;
1998
1999         case 'Y':
2000            SendMessage(info->wnd, WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0);
2001            return 1;
2002
2003         case 'R':
2004            SendMessage(info->wnd, WM_COMMAND, ID_REVERSE_VIEW, 0);
2005            return 1;
2006
2007         case 'P':
2008            SendMessage(info->wnd, WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0);
2009            return 1;
2010
2011         case 'O':
2012            SendMessage(info->wnd, WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0);
2013            return 1;
2014      }
2015   }
2016   return global_handle_key(info, wparam, lparam);
2017}
2018
2019
2020
2021//============================================================
2022//  memory_update_caption
2023//============================================================
2024
2025static void memory_update_caption(running_machine &machine, HWND wnd)
2026{
2027   debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
2028   astring title;
2029
2030   title.printf("Memory: %s", info->view[0].view->source()->name());
2031   win_set_window_text_utf8(wnd, title);
2032}
2033
2034
2035
2036//============================================================
2037//  disasm_create_window
2038//============================================================
2039
2040static void disasm_create_window(running_machine &machine)
2041{
2042   device_t *curcpu = debug_cpu_get_visible_cpu(machine);
2043   debugwin_info *info;
2044   HMENU optionsmenu;
2045
2046   // create the window
2047   info = debugwin_window_create(machine, "Disassembly", NULL);
2048   if (info == NULL || !debugwin_view_create(info, 0, DVT_DISASSEMBLY))
2049      return;
2050
2051   // create the options menu
2052   optionsmenu = CreatePopupMenu();
2053   AppendMenu(optionsmenu, MF_ENABLED, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9"));
2054   AppendMenu(optionsmenu, MF_ENABLED, ID_RUN_TO_CURSOR, TEXT("Run to cursor\tF4"));
2055   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
2056   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_RAW, TEXT("Raw opcodes\tCtrl+R"));
2057   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_ENCRYPTED, TEXT("Encrypted opcodes\tCtrl+E"));
2058   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_COMMENTS, TEXT("Comments\tCtrl+M"));
2059   AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
2060
2061   // set the handlers
2062   info->handle_command = disasm_handle_command;
2063   info->handle_key = disasm_handle_key;
2064   info->update_menu = disasm_update_menu;
2065
2066   // set up the view to track the initial expression
2067   downcast<debug_view_disasm *>(info->view[0].view)->set_expression("curpc");
2068   strcpy(info->edit_defstr, "curpc");
2069
2070   // create an edit box and override its key handling
2071   info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
2072         0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL);
2073   info->original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC);
2074   SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info);
2075   SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc);
2076   SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
2077   SendMessage(info->editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("curpc"));
2078   SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
2079   SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
2080
2081   // create a combo box
2082   info->otherwnd[0] = CreateWindowEx(COMBO_BOX_STYLE_EX, TEXT("COMBOBOX"), NULL, COMBO_BOX_STYLE,
2083         0, 0, 100, 1000, info->wnd, NULL, GetModuleHandle(NULL), NULL);
2084   SetWindowLongPtr(info->otherwnd[0], GWLP_USERDATA, (LONG_PTR)info);
2085   SendMessage(info->otherwnd[0], WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
2086
2087   // populate the combobox
2088   int maxlength = 0;
2089   for (const debug_view_source *source = info->view[0].view->first_source(); source != NULL; source = source->next())
2090   {
2091      int length = strlen(source->name());
2092      if (length > maxlength)
2093         maxlength = length;
2094      TCHAR *t_name = tstring_from_utf8(source->name());
2095      SendMessage(info->otherwnd[0], CB_ADDSTRING, 0, (LPARAM)t_name);
2096      osd_free(t_name);
2097   }
2098   const debug_view_source *source = info->view[0].view->source_for_device(curcpu);
2099   SendMessage(info->otherwnd[0], CB_SETCURSEL, info->view[0].view->source_list().indexof(*source), 0);
2100   SendMessage(info->otherwnd[0], CB_SETDROPPEDWIDTH, (maxlength + 2) * debug_font_width + vscroll_width, 0);
2101   info->view[0].view->set_source(*source);
2102
2103   // set the child functions
2104   info->recompute_children = disasm_recompute_children;
2105   info->process_string = disasm_process_string;
2106
2107   // set the caption
2108   disasm_update_caption(machine, info->wnd);
2109
2110   // recompute the children once to get the maxwidth
2111   disasm_recompute_children(info);
2112
2113   // position the window and recompute children again
2114   SetWindowPos(info->wnd, HWND_TOP, 100, 100, info->maxwidth, 200, SWP_SHOWWINDOW);
2115   disasm_recompute_children(info);
2116
2117   // mark the edit box as the default focus and set it
2118   info->focuswnd = info->editwnd;
2119   SetFocus(info->editwnd);
2120}
2121
2122
2123
2124//============================================================
2125//  disasm_recompute_children
2126//============================================================
2127
2128static void disasm_recompute_children(debugwin_info *info)
2129{
2130   debug_view_xy totalsize = info->view[0].view->total_size();
2131   RECT parent, dasmrect, editrect, comborect;
2132   RECT bounds;
2133
2134   // compute a client rect
2135   bounds.top = bounds.left = 0;
2136   bounds.right = totalsize.x * debug_font_width + vscroll_width + 2 * EDGE_WIDTH;
2137   bounds.bottom = 200;
2138   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
2139
2140   // clamp the min/max size
2141   info->maxwidth = bounds.right - bounds.left;
2142
2143   // get the parent's dimensions
2144   GetClientRect(info->wnd, &parent);
2145
2146   // edit box gets half of the width
2147   editrect.top = parent.top + EDGE_WIDTH;
2148   editrect.bottom = editrect.top + debug_font_height + 4;
2149   editrect.left = parent.left + EDGE_WIDTH;
2150   editrect.right = parent.left + (parent.right - parent.left) / 2 - EDGE_WIDTH;
2151
2152   // combo box gets the other half of the width
2153   comborect.top = editrect.top;
2154   comborect.bottom = editrect.bottom;
2155   comborect.left = editrect.right + 2 * EDGE_WIDTH;
2156   comborect.right = parent.right - EDGE_WIDTH;
2157
2158   // disasm view gets the rest
2159   dasmrect.top = editrect.bottom + 2 * EDGE_WIDTH;
2160   dasmrect.bottom = parent.bottom - EDGE_WIDTH;
2161   dasmrect.left = parent.left + EDGE_WIDTH;
2162   dasmrect.right = parent.right - EDGE_WIDTH;
2163
2164   // set the bounds of things
2165   debugwin_view_set_bounds(&info->view[0], info->wnd, &dasmrect);
2166   smart_set_window_bounds(info->editwnd, info->wnd, &editrect);
2167   smart_set_window_bounds(info->otherwnd[0], info->wnd, &comborect);
2168}
2169
2170
2171
2172//============================================================
2173//  disasm_process_string
2174//============================================================
2175
2176static void disasm_process_string(debugwin_info *info, const char *string)
2177{
2178   // set the string to the disasm view
2179   downcast<debug_view_disasm *>(info->view[0].view)->set_expression(string);
2180
2181   // select everything in the edit text box
2182   SendMessage(info->editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
2183
2184   // update the default string to match
2185   strncpy(info->edit_defstr, string, sizeof(info->edit_defstr) - 1);
2186}
2187
2188
2189
2190//============================================================
2191//  disasm_update_menu
2192//============================================================
2193
2194static void disasm_update_menu(debugwin_info *info)
2195{
2196   disasm_right_column rightcol = downcast<debug_view_disasm *>(info->view[0].view)->right_column();
2197   CheckMenuItem(GetMenu(info->wnd), ID_SHOW_RAW, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_RAW ? MF_CHECKED : MF_UNCHECKED));
2198   CheckMenuItem(GetMenu(info->wnd), ID_SHOW_ENCRYPTED, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_ENCRYPTED ? MF_CHECKED : MF_UNCHECKED));
2199   CheckMenuItem(GetMenu(info->wnd), ID_SHOW_COMMENTS, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_COMMENTS ? MF_CHECKED : MF_UNCHECKED));
2200}
2201
2202
2203
2204//============================================================
2205//  disasm_handle_command
2206//============================================================
2207
2208static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam)
2209{
2210   debug_view_disasm *dasmview = downcast<debug_view_disasm *>(info->view[0].view);
2211   char command[64];
2212
2213   switch (HIWORD(wparam))
2214   {
2215      // combo box selection changed
2216      case CBN_SELCHANGE:
2217      {
2218         int sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
2219         if (sel != CB_ERR)
2220         {
2221            dasmview->set_source(*dasmview->source_list().find(sel));
2222            disasm_update_caption(info->machine(), info->wnd);
2223
2224            // reset the focus
2225            SetFocus(info->focuswnd);
2226            return 1;
2227         }
2228         break;
2229      }
2230
2231      // menu selections
2232      case 0:
2233         switch (LOWORD(wparam))
2234         {
2235            case ID_SHOW_RAW:
2236               dasmview->set_right_column(DASM_RIGHTCOL_RAW);
2237               (*info->recompute_children)(info);
2238               return 1;
2239
2240            case ID_SHOW_ENCRYPTED:
2241               dasmview->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
2242               (*info->recompute_children)(info);
2243               return 1;
2244
2245            case ID_SHOW_COMMENTS:
2246               dasmview->set_right_column(DASM_RIGHTCOL_COMMENTS);
2247               (*info->recompute_children)(info);
2248               return 1;
2249
2250            case ID_RUN_TO_CURSOR:
2251               if (dasmview->cursor_visible() && debug_cpu_get_visible_cpu(info->machine()) == dasmview->source()->device())
2252               {
2253                  offs_t address = dasmview->selected_address();
2254                  sprintf(command, "go 0x%X", address);
2255                  debug_console_execute_command(info->machine(), command, 1);
2256               }
2257               return 1;
2258
2259            case ID_TOGGLE_BREAKPOINT:
2260               if (dasmview->cursor_visible() && debug_cpu_get_visible_cpu(info->machine()) == dasmview->source()->device())
2261               {
2262                  offs_t address = dasmview->selected_address();
2263                  device_debug *debug = dasmview->source()->device()->debug();
2264                  INT32 bpindex = -1;
2265
2266                  /* first find an existing breakpoint at this address */
2267                  for (device_debug::breakpoint *bp = debug->breakpoint_first(); bp != NULL; bp = bp->next())
2268                     if (address == bp->address())
2269                     {
2270                        bpindex = bp->index();
2271                        break;
2272                     }
2273
2274                  /* if it doesn't exist, add a new one */
2275                  if (bpindex == -1)
2276                     sprintf(command, "bpset 0x%X", address);
2277                  else
2278                     sprintf(command, "bpclear 0x%X", bpindex);
2279                  debug_console_execute_command(info->machine(), command, 1);
2280               }
2281               return 1;
2282         }
2283         break;
2284   }
2285   return global_handle_command(info, wparam, lparam);
2286}
2287
2288
2289
2290//============================================================
2291//  disasm_handle_key
2292//============================================================
2293
2294static int disasm_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam)
2295{
2296   if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
2297   {
2298      switch (wparam)
2299      {
2300         case 'R':
2301            SendMessage(info->wnd, WM_COMMAND, ID_SHOW_RAW, 0);
2302            return 1;
2303
2304         case 'E':
2305            SendMessage(info->wnd, WM_COMMAND, ID_SHOW_ENCRYPTED, 0);
2306            return 1;
2307
2308         case 'N':
2309            SendMessage(info->wnd, WM_COMMAND, ID_SHOW_COMMENTS, 0);
2310            return 1;
2311      }
2312   }
2313
2314   switch (wparam)
2315   {
2316      /* ajg - steals the F4 from the global key handler - but ALT+F4 didn't work anyways ;) */
2317      case VK_F4:
2318         SendMessage(info->wnd, WM_COMMAND, ID_RUN_TO_CURSOR, 0);
2319         return 1;
2320
2321      case VK_F9:
2322         SendMessage(info->wnd, WM_COMMAND, ID_TOGGLE_BREAKPOINT, 0);
2323         return 1;
2324
2325      case VK_RETURN:
2326         if (info->view[0].view->cursor_visible())
2327         {
2328            SendMessage(info->wnd, WM_COMMAND, ID_STEP, 0);
2329            return 1;
2330         }
2331         break;
2332   }
2333
2334   return global_handle_key(info, wparam, lparam);
2335}
2336
2337
2338
2339//============================================================
2340//  disasm_update_caption
2341//============================================================
2342
2343static void disasm_update_caption(running_machine &machine, HWND wnd)
2344{
2345   debugwin_info *info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
2346   astring title;
2347
2348   title.printf("Disassembly: %s", info->view[0].view->source()->name());
2349   win_set_window_text_utf8(wnd, title);
2350}
2351
2352
2353enum
2354{
2355   DEVOPTION_OPEN,
2356   DEVOPTION_CREATE,
2357   DEVOPTION_CLOSE,
2358   DEVOPTION_CASSETTE_STOPPAUSE,
2359   DEVOPTION_CASSETTE_PLAY,
2360   DEVOPTION_CASSETTE_RECORD,
2361   DEVOPTION_CASSETTE_REWIND,
2362   DEVOPTION_CASSETTE_FASTFORWARD,
2363   DEVOPTION_MAX
2364};
2365
2366//============================================================
2367//  memory_update_menu
2368//============================================================
2369
2370static void image_update_menu(debugwin_info *info)
2371{
2372   UINT32 cnt = 0;
2373   HMENU devicesmenu;
2374
2375   DeleteMenu(GetMenu(info->wnd), 2, MF_BYPOSITION);
2376
2377   // create the image menu
2378   devicesmenu = CreatePopupMenu();
2379   image_interface_iterator iter(info->machine().root_device());
2380   for (device_image_interface *img = iter.first(); img != NULL; img = iter.next())
2381   {
2382      astring temp;
2383      UINT flags_for_exists;
2384      UINT flags_for_writing;
2385      HMENU devicesubmenu = CreatePopupMenu();
2386
2387      UINT_PTR new_item = ID_DEVICE_OPTIONS + (cnt * DEVOPTION_MAX);
2388
2389      flags_for_exists = MF_ENABLED | MF_STRING;
2390
2391      if (!img->exists())
2392         flags_for_exists |= MF_GRAYED;
2393
2394      flags_for_writing = flags_for_exists;
2395      if (img->is_readonly())
2396         flags_for_writing |= MF_GRAYED;
2397
2398      AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount..."));
2399
2400      /*if (img->is_creatable())
2401          AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_CREATE, TEXT("Create..."));
2402      */
2403      AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CLOSE, TEXT("Unmount"));
2404
2405      if (img->device().type() == CASSETTE)
2406      {
2407         cassette_state state;
2408         state = (cassette_state)(img->exists() ? (dynamic_cast<cassette_image_device*>(&img->device())->get_state() & CASSETTE_MASK_UISTATE) : CASSETTE_STOPPED);
2409         AppendMenu(devicesubmenu, MF_SEPARATOR, 0, NULL);
2410         AppendMenu(devicesubmenu, flags_for_exists  | ((state == CASSETTE_STOPPED)  ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_STOPPAUSE, TEXT("Pause/Stop"));
2411         AppendMenu(devicesubmenu, flags_for_exists  | ((state == CASSETTE_PLAY) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_PLAY, TEXT("Play"));
2412         AppendMenu(devicesubmenu, flags_for_writing | ((state == CASSETTE_RECORD)   ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_RECORD, TEXT("Record"));
2413         AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_REWIND, TEXT("Rewind"));
2414         AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_FASTFORWARD, TEXT("Fast Forward"));
2415      }
2416
2417      temp.format("%s :%s", img->device().name(), img->exists() ? img->filename() : "[empty slot]");
2418
2419      AppendMenu(devicesmenu, MF_ENABLED | MF_POPUP, (UINT_PTR)devicesubmenu,  tstring_from_utf8(temp.cstr()));
2420
2421      cnt++;
2422   }
2423   AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)devicesmenu, TEXT("Images"));
2424
2425}
2426
2427//============================================================
2428//  console_create_window
2429//============================================================
2430
2431void console_create_window(running_machine &machine)
2432{
2433   debugwin_info *info;
2434   int bestwidth, bestheight;
2435   RECT bounds, work_bounds;
2436   HMENU optionsmenu;
2437   UINT32 conchars;
2438
2439   // create the window
2440   info = debugwin_window_create(machine, "Debug", NULL);
2441   if (info == NULL)
2442      return;
2443   main_console = info;
2444
2445   // create the views
2446   if (!debugwin_view_create(info, 0, DVT_DISASSEMBLY))
2447      goto cleanup;
2448   if (!debugwin_view_create(info, 1, DVT_STATE))
2449      goto cleanup;
2450   if (!debugwin_view_create(info, 2, DVT_CONSOLE))
2451      goto cleanup;
2452
2453   // create the options menu
2454   optionsmenu = CreatePopupMenu();
2455   AppendMenu(optionsmenu, MF_ENABLED, ID_TOGGLE_BREAKPOINT, TEXT("Set breakpoint at cursor\tF9"));
2456   AppendMenu(optionsmenu, MF_ENABLED, ID_RUN_TO_CURSOR, TEXT("Run to cursor\tF4"));
2457   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
2458   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_RAW, TEXT("Raw opcodes\tCtrl+R"));
2459   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_ENCRYPTED, TEXT("Encrypted opcodes\tCtrl+E"));
2460   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_COMMENTS, TEXT("Comments\tCtrl+N"));
2461   AppendMenu(GetMenu(info->wnd), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
2462
2463   // Add image menu only if image devices exist
2464   {
2465      image_interface_iterator iter(machine.root_device());
2466      if (iter.first() != NULL) {
2467         info->update_menu = image_update_menu;
2468         image_update_menu(info);
2469      }
2470   }
2471
2472   // set the handlers
2473   info->handle_command = disasm_handle_command;
2474   info->handle_key = disasm_handle_key;
2475
2476   // create an edit box and override its key handling
2477   info->editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
2478         0, 0, 100, 100, info->wnd, NULL, GetModuleHandle(NULL), NULL);
2479   info->original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(info->editwnd, GWLP_WNDPROC);
2480   SetWindowLongPtr(info->editwnd, GWLP_USERDATA, (LONG_PTR)info);
2481   SetWindowLongPtr(info->editwnd, GWLP_WNDPROC, (LONG_PTR)debugwin_edit_proc);
2482   SendMessage(info->editwnd, WM_SETFONT, (WPARAM)debug_font, (LPARAM)FALSE);
2483   SendMessage(info->editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
2484
2485   // set the child functions
2486   info->recompute_children = console_recompute_children;
2487   info->process_string = console_process_string;
2488
2489   // loop over all register views and get the maximum size
2490   main_console_regwidth = 0;
2491   for (const debug_view_source *source = info->view[1].view->first_source(); source != NULL; source = source->next())
2492   {
2493      UINT32 regchars;
2494
2495      // set the view and fetch the width
2496      info->view[1].view->set_source(*source);
2497      regchars = info->view[1].view->total_size().x;
2498
2499      // track the maximum
2500      main_console_regwidth = MAX(regchars, main_console_regwidth);
2501   }
2502
2503   // determine the width of the console (this is fixed)
2504   conchars = info->view[2].view->total_size().x;
2505
2506   // loop over all CPUs and compute the width range based on dasm width
2507   info->minwidth = 0;
2508   info->maxwidth = 0;
2509   for (const debug_view_source *source = info->view[0].view->first_source(); source != NULL; source = source->next())
2510   {
2511      UINT32 minwidth, maxwidth, dischars;
2512
2513      // set the view and fetch the width
2514      info->view[0].view->set_source(*source);
2515      dischars = info->view[0].view->total_size().x;
2516
2517      // compute the preferred width
2518      minwidth = EDGE_WIDTH + main_console_regwidth * debug_font_width + vscroll_width + 2 * EDGE_WIDTH + 100 + EDGE_WIDTH;
2519      maxwidth = EDGE_WIDTH + main_console_regwidth * debug_font_width + vscroll_width + 2 * EDGE_WIDTH + MAX(dischars, conchars) * debug_font_width + vscroll_width + EDGE_WIDTH;
2520      info->minwidth = MAX(info->minwidth, minwidth);
2521      info->maxwidth = MAX(info->maxwidth, maxwidth);
2522   }
2523
2524   // get the work bounds
2525   SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
2526
2527   // adjust the min/max sizes for the window style
2528   bounds.top = bounds.left = 0;
2529   bounds.right = bounds.bottom = info->minwidth;
2530   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
2531   info->minwidth = bounds.right - bounds.left;
2532
2533   bounds.top = bounds.left = 0;
2534   bounds.right = bounds.bottom = info->maxwidth;
2535   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
2536   info->maxwidth = bounds.right - bounds.left;
2537
2538   // position the window at the bottom-right
2539   bestwidth = (info->maxwidth < (work_bounds.right - work_bounds.left)) ? info->maxwidth : (work_bounds.right - work_bounds.left);
2540   bestheight = (500 < (work_bounds.bottom - work_bounds.top)) ? 500 : (work_bounds.bottom - work_bounds.top);
2541   SetWindowPos(info->wnd, HWND_TOP,
2542            work_bounds.right - bestwidth, work_bounds.bottom - bestheight,
2543            bestwidth, bestheight,
2544            SWP_SHOWWINDOW);
2545
2546   // recompute the children
2547   console_set_cpu(debug_cpu_get_visible_cpu(machine));
2548
2549   // set up the disassembly view to track the current pc
2550   downcast<debug_view_disasm *>(info->view[0].view)->set_expression("curpc");
2551
2552   // mark the edit box as the default focus and set it
2553   info->focuswnd = info->editwnd;
2554   SetFocus(info->editwnd);
2555   return;
2556
2557cleanup:
2558   if (info->view[2].view)
2559      machine.debug_view().free_view(*info->view[2].view);
2560   if (info->view[1].view)
2561      machine.debug_view().free_view(*info->view[1].view);
2562   if (info->view[0].view)
2563      machine.debug_view().free_view(*info->view[0].view);
2564}
2565
2566
2567
2568//============================================================
2569//  console_recompute_children
2570//============================================================
2571
2572static void console_recompute_children(debugwin_info *info)
2573{
2574   RECT parent, regrect, disrect, conrect, editrect;
2575   UINT32 regchars;//, dischars, conchars;
2576
2577   // get the parent's dimensions
2578   GetClientRect(info->wnd, &parent);
2579
2580   // get the total width of all three children
2581   //dischars = info->view[0].view->total_size().x;
2582   regchars = main_console_regwidth;
2583   //conchars = info->view[2].view->total_size().x;
2584
2585   // registers always get their desired width, and span the entire height
2586   regrect.top = parent.top + EDGE_WIDTH;
2587   regrect.bottom = parent.bottom - EDGE_WIDTH;
2588   regrect.left = parent.left + EDGE_WIDTH;
2589   regrect.right = regrect.left + debug_font_width * regchars + vscroll_width;
2590
2591   // edit box goes at the bottom of the remaining area
2592   editrect.bottom = parent.bottom - EDGE_WIDTH;
2593   editrect.top = editrect.bottom - debug_font_height - 4;
2594   editrect.left = regrect.right + EDGE_WIDTH * 2;
2595   editrect.right = parent.right - EDGE_WIDTH;
2596
2597   // console and disassembly split the difference
2598   disrect.top = parent.top + EDGE_WIDTH;
2599   disrect.bottom = (editrect.top - parent.top) / 2 - EDGE_WIDTH;
2600   disrect.left = regrect.right + EDGE_WIDTH * 2;
2601   disrect.right = parent.right - EDGE_WIDTH;
2602
2603   conrect.top = disrect.bottom + EDGE_WIDTH * 2;
2604   conrect.bottom = editrect.top - EDGE_WIDTH;
2605   conrect.left = regrect.right + EDGE_WIDTH * 2;
2606   conrect.right = parent.right - EDGE_WIDTH;
2607
2608   // set the bounds of things
2609   debugwin_view_set_bounds(&info->view[0], info->wnd, &disrect);
2610   debugwin_view_set_bounds(&info->view[1], info->wnd, &regrect);
2611   debugwin_view_set_bounds(&info->view[2], info->wnd, &conrect);
2612   smart_set_window_bounds(info->editwnd, info->wnd, &editrect);
2613}
2614
2615
2616
2617//============================================================
2618//  console_process_string
2619//============================================================
2620
2621static void console_process_string(debugwin_info *info, const char *string)
2622{
2623   TCHAR buffer = 0;
2624
2625   // an empty string is a single step
2626   if (string[0] == 0)
2627      debug_cpu_get_visible_cpu(info->machine())->debug()->single_step();
2628
2629   // otherwise, just process the command
2630253   else
2631      debug_console_execute_command(info->machine(), string, 1);
2632
2633   // clear the edit text box
2634   SendMessage(info->editwnd, WM_SETTEXT, 0, (LPARAM)&buffer);
2635}
2636
2637
2638
2639//============================================================
2640//  console_set_cpu
2641//============================================================
2642
2643static void console_set_cpu(device_t *device)
2644{
2645   // first set all the views to the new cpu number
2646   main_console->view[0].view->set_source(*main_console->view[0].view->source_for_device(device));
2647   main_console->view[1].view->set_source(*main_console->view[1].view->source_for_device(device));
2648
2649   // then update the caption
2650   char curtitle[256];
2651   astring title;
2652
2653   title.printf("Debug: %s - %s '%s'", device->machine().system().name, device->name(), device->tag());
2654   win_get_window_text_utf8(main_console->wnd, curtitle, ARRAY_LENGTH(curtitle));
2655   if (title.cmp(curtitle) != 0)
2656      win_set_window_text_utf8(main_console->wnd, title);
2657
2658   // and recompute the children
2659   console_recompute_children(main_console);
2660}
2661
2662
2663
2664//============================================================
2665//  create_standard_menubar
2666//============================================================
2667
2668static HMENU create_standard_menubar(void)
2669{
2670   HMENU menubar, debugmenu;
2671
2672   // create the debug menu
2673   debugmenu = CreatePopupMenu();
2674   if (debugmenu == NULL)
2675      return NULL;
2676   AppendMenu(debugmenu, MF_ENABLED, ID_NEW_MEMORY_WND, TEXT("New Memory Window\tCtrl+M"));
2677   AppendMenu(debugmenu, MF_ENABLED, ID_NEW_DISASM_WND, TEXT("New Disassembly Window\tCtrl+D"));
2678   AppendMenu(debugmenu, MF_ENABLED, ID_NEW_LOG_WND, TEXT("New Error Log Window\tCtrl+L"));
2679   AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
2680   AppendMenu(debugmenu, MF_ENABLED, ID_RUN, TEXT("Run\tF5"));
2681   AppendMenu(debugmenu, MF_ENABLED, ID_RUN_AND_HIDE, TEXT("Run and Hide Debugger\tF12"));
2682   AppendMenu(debugmenu, MF_ENABLED, ID_NEXT_CPU, TEXT("Run to Next CPU\tF6"));
2683   AppendMenu(debugmenu, MF_ENABLED, ID_RUN_IRQ, TEXT("Run until Next Interrupt on This CPU\tF7"));
2684   AppendMenu(debugmenu, MF_ENABLED, ID_RUN_VBLANK, TEXT("Run until Next VBLANK\tF8"));
2685   AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
2686   AppendMenu(debugmenu, MF_ENABLED, ID_STEP, TEXT("Step Into\tF11"));
2687   AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OVER, TEXT("Step Over\tF10"));
2688   AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OUT, TEXT("Step Out\tShift+F11"));
2689   AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
2690   AppendMenu(debugmenu, MF_ENABLED, ID_SOFT_RESET, TEXT("Soft Reset\tF3"));
2691   AppendMenu(debugmenu, MF_ENABLED, ID_HARD_RESET, TEXT("Hard Reset\tShift+F3"));
2692   AppendMenu(debugmenu, MF_ENABLED, ID_EXIT, TEXT("Exit"));
2693
2694   // create the menu bar
2695   menubar = CreateMenu();
2696   if (menubar == NULL)
2697254   {
2698      DestroyMenu(debugmenu);
255      global_free(info);
2699256      return NULL;
2700257   }
2701   AppendMenu(menubar, MF_ENABLED | MF_POPUP, (UINT_PTR)debugmenu, TEXT("Debug"));
2702
2703   return menubar;
2704258}
2705259
2706//============================================================
2707//  copy_extension_list
2708//============================================================
2709260
2710static int copy_extension_list(char *dest, size_t dest_len, const char *extensions)
2711{
2712   const char *s;
2713   int pos = 0;
2714
2715   // our extension lists are comma delimited; Win32 expects to see lists
2716   // delimited by semicolons
2717   s = extensions;
2718   while(*s)
2719   {
2720      // append a semicolon if not at the beginning
2721      if (s != extensions)
2722         pos += snprintf(&dest[pos], dest_len - pos, ";");
2723
2724      // append ".*"
2725      pos += snprintf(&dest[pos], dest_len - pos, "*.");
2726
2727      // append the file extension
2728      while(*s && (*s != ','))
2729      {
2730         pos += snprintf(&dest[pos], dest_len - pos, "%c", *s);
2731         s++;
2732      }
2733
2734      // if we found a comma, advance
2735      while(*s == ',')
2736         s++;
2737   }
2738   return pos;
2739}
2740
2741//============================================================
2742//  add_filter_entry
2743//============================================================
2744
2745static int add_filter_entry(char *dest, size_t dest_len, const char *description, const char *extensions)
2746{
2747   int pos = 0;
2748
2749   // add the description
2750   pos += snprintf(&dest[pos], dest_len - pos, "%s (", description);
2751
2752   // add the extensions to the description
2753   pos += copy_extension_list(&dest[pos], dest_len - pos, extensions);
2754
2755   // add the trailing rparen and '|' character
2756   pos += snprintf(&dest[pos], dest_len - pos, ")|");
2757
2758   // now add the extension list itself
2759   pos += copy_extension_list(&dest[pos], dest_len - pos, extensions);
2760
2761   // append a '|'
2762   pos += snprintf(&dest[pos], dest_len - pos, "|");
2763
2764   return pos;
2765}
2766//============================================================
2767//  build_generic_filter
2768//============================================================
2769
2770static void build_generic_filter(device_image_interface *img, int is_save, char *filter, size_t filter_len)
2771{
2772   char *s;
2773
2774   const char *file_extension;
2775
2776   /* copy the string */
2777   file_extension = img->file_extensions();
2778
2779   // start writing the filter
2780   s = filter;
2781
2782   // common image types
2783   s += add_filter_entry(filter, filter_len, "Common image types", file_extension);
2784
2785   // all files
2786   s += sprintf(s, "All files (*.*)|*.*|");
2787
2788   // compressed
2789   if (!is_save)
2790      s += sprintf(s, "Compressed Images (*.zip)|*.zip|");
2791
2792   *(s++) = '\0';
2793}
2794
2795//============================================================
2796//  global_handle_command
2797//============================================================
2798
2799static int global_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lparam)
2800{
2801   if (HIWORD(wparam) == 0)
2802      switch (LOWORD(wparam))
2803      {
2804         case ID_NEW_MEMORY_WND:
2805            memory_create_window(info->machine());
2806            return 1;
2807
2808         case ID_NEW_DISASM_WND:
2809            disasm_create_window(info->machine());
2810            return 1;
2811
2812         case ID_NEW_LOG_WND:
2813            log_create_window(info->machine());
2814            return 1;
2815
2816         case ID_RUN_AND_HIDE:
2817            smart_show_all(FALSE);
2818         case ID_RUN:
2819            debug_cpu_get_visible_cpu(info->machine())->debug()->go();
2820            return 1;
2821
2822         case ID_NEXT_CPU:
2823            debug_cpu_get_visible_cpu(info->machine())->debug()->go_next_device();
2824            return 1;
2825
2826         case ID_RUN_VBLANK:
2827            debug_cpu_get_visible_cpu(info->machine())->debug()->go_vblank();
2828            return 1;
2829
2830         case ID_RUN_IRQ:
2831            debug_cpu_get_visible_cpu(info->machine())->debug()->go_interrupt();
2832            return 1;
2833
2834         case ID_STEP:
2835            debug_cpu_get_visible_cpu(info->machine())->debug()->single_step();
2836            return 1;
2837
2838         case ID_STEP_OVER:
2839            debug_cpu_get_visible_cpu(info->machine())->debug()->single_step_over();
2840            return 1;
2841
2842         case ID_STEP_OUT:
2843            debug_cpu_get_visible_cpu(info->machine())->debug()->single_step_out();
2844            return 1;
2845
2846         case ID_HARD_RESET:
2847            info->machine().schedule_hard_reset();
2848            return 1;
2849
2850         case ID_SOFT_RESET:
2851            info->machine().schedule_soft_reset();
2852            debug_cpu_get_visible_cpu(info->machine())->debug()->go();
2853            return 1;
2854
2855         case ID_EXIT:
2856            if (info->focuswnd != NULL)
2857               SetFocus(info->focuswnd);
2858            info->machine().schedule_exit();
2859            return 1;
2860      }
2861      if (LOWORD(wparam) >= ID_DEVICE_OPTIONS) {
2862         UINT32 devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX;
2863         image_interface_iterator iter(info->machine().root_device());
2864         device_image_interface *img = iter.byindex(devid);
2865         if (img!=NULL) {
2866            switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
2867            {
2868               case DEVOPTION_OPEN :
2869                                 {
2870                                    char filter[2048];
2871                                    build_generic_filter(img, FALSE, filter, ARRAY_LENGTH(filter));
2872
2873                                    TCHAR selectedFilename[MAX_PATH];
2874                                    selectedFilename[0] = '\0';
2875                                    LPTSTR buffer;
2876                                    LPTSTR t_filter = NULL;
2877
2878                                    buffer = tstring_from_utf8(filter);
2879
2880                                    // convert a pipe-char delimited string into a NUL delimited string
2881                                    t_filter = (LPTSTR) alloca((_tcslen(buffer) + 2) * sizeof(*t_filter));
2882                                    int i = 0;
2883                                    for (i = 0; buffer[i] != '\0'; i++)
2884                                       t_filter[i] = (buffer[i] != '|') ? buffer[i] : '\0';
2885                                    t_filter[i++] = '\0';
2886                                    t_filter[i++] = '\0';
2887                                    osd_free(buffer);
2888
2889
2890                                    OPENFILENAME  ofn;
2891                                    memset(&ofn,0,sizeof(ofn));
2892                                    ofn.lStructSize = sizeof(ofn);
2893                                    ofn.hwndOwner = NULL;
2894                                    ofn.lpstrFile = selectedFilename;
2895                                    ofn.lpstrFile[0] = '\0';
2896                                    ofn.nMaxFile = MAX_PATH;
2897                                    ofn.lpstrFilter = t_filter;
2898                                    ofn.nFilterIndex = 1;
2899                                    ofn.lpstrFileTitle = NULL;
2900                                    ofn.nMaxFileTitle = 0;
2901                                    ofn.lpstrInitialDir = NULL;
2902                                    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
2903
2904                                    if (GetOpenFileName(&ofn)) {
2905                                       img->load(utf8_from_tstring(selectedFilename));
2906                                    }
2907                                 }
2908                                 return 1;
2909/*                  case DEVOPTION_CREATE:
2910                                            return 1;*/
2911               case DEVOPTION_CLOSE:
2912                                 img->unload();
2913                                 return 1;
2914               default:
2915                  if (img->device().type() == CASSETTE) {
2916                     cassette_image_device* cassette = dynamic_cast<cassette_image_device*>(&img->device());
2917                     switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
2918                     {
2919                        case DEVOPTION_CASSETTE_STOPPAUSE:
2920                                          cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
2921                                          return 1;
2922                        case DEVOPTION_CASSETTE_PLAY:
2923                                          cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
2924                                          return 1;
2925                        case DEVOPTION_CASSETTE_RECORD:
2926                                          cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
2927                                          return 1;
2928                        case DEVOPTION_CASSETTE_REWIND:
2929                                          cassette->seek(-60.0, SEEK_CUR);
2930                                          return 1;
2931                        case DEVOPTION_CASSETTE_FASTFORWARD:
2932                                          cassette->seek(+60.0, SEEK_CUR);
2933                                          return 1;
2934                     }
2935                  }
2936            }
2937         }
2938      }
2939   return 0;
2940}
2941
2942
2943
2944//============================================================
2945//  global_handle_key
2946//============================================================
2947
2948static int global_handle_key(debugwin_info *info, WPARAM wparam, LPARAM lparam)
2949{
2950   /* ignore any keys that are received while the debug key is down */
2951   if (!waiting_for_debugger && debugwin_seq_pressed(info->machine()))
2952      return 1;
2953
2954   switch (wparam)
2955   {
2956      case VK_F3:
2957         if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
2958            SendMessage(info->wnd, WM_COMMAND, ID_HARD_RESET, 0);
2959         else
2960            SendMessage(info->wnd, WM_COMMAND, ID_SOFT_RESET, 0);
2961         return 1;
2962
2963      case VK_F4:
2964         if (GetAsyncKeyState(VK_MENU) & 0x8000)
2965         {
2966            /* ajg - never gets here since 'alt' seems to be captured somewhere else - menu maybe? */
2967            SendMessage(info->wnd, WM_COMMAND, ID_EXIT, 0);
2968            return 1;
2969         }
2970         break;
2971
2972      case VK_F5:
2973         SendMessage(info->wnd, WM_COMMAND, ID_RUN, 0);
2974         return 1;
2975
2976      case VK_F6:
2977         SendMessage(info->wnd, WM_COMMAND, ID_NEXT_CPU, 0);
2978         return 1;
2979
2980      case VK_F7:
2981         SendMessage(info->wnd, WM_COMMAND, ID_RUN_IRQ, 0);
2982         return 1;
2983
2984      case VK_F8:
2985         SendMessage(info->wnd, WM_COMMAND, ID_RUN_VBLANK, 0);
2986         return 1;
2987
2988      case VK_F10:
2989         SendMessage(info->wnd, WM_COMMAND, ID_STEP_OVER, 0);
2990         return 1;
2991
2992      case VK_F11:
2993         if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
2994            SendMessage(info->wnd, WM_COMMAND, ID_STEP_OUT, 0);
2995         else
2996            SendMessage(info->wnd, WM_COMMAND, ID_STEP, 0);
2997         return 1;
2998
2999      case VK_F12:
3000         SendMessage(info->wnd, WM_COMMAND, ID_RUN_AND_HIDE, 0);
3001         return 1;
3002
3003      case 'M':
3004         if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
3005         {
3006            SendMessage(info->wnd, WM_COMMAND, ID_NEW_MEMORY_WND, 0);
3007            return 1;
3008         }
3009         break;
3010
3011      case 'D':
3012         if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
3013         {
3014            SendMessage(info->wnd, WM_COMMAND, ID_NEW_DISASM_WND, 0);
3015            return 1;
3016         }
3017         break;
3018
3019      case 'L':
3020         if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
3021         {
3022            SendMessage(info->wnd, WM_COMMAND, ID_NEW_LOG_WND, 0);
3023            return 1;
3024         }
3025         break;
3026   }
3027
3028   return 0;
3029}
3030
3031
3032
3033//============================================================
3034//  smart_set_window_bounds
3035//============================================================
3036
3037static void smart_set_window_bounds(HWND wnd, HWND parent, RECT *bounds)
3038{
3039   RECT curbounds;
3040   int flags = 0;
3041
3042   // first get the current bounds, relative to the parent
3043   GetWindowRect(wnd, &curbounds);
3044   if (parent != NULL)
3045   {
3046      RECT parentbounds;
3047      GetWindowRect(parent, &parentbounds);
3048      curbounds.top -= parentbounds.top;
3049      curbounds.bottom -= parentbounds.top;
3050      curbounds.left -= parentbounds.left;
3051      curbounds.right -= parentbounds.left;
3052   }
3053
3054   // if the position matches, don't change it
3055   if (curbounds.top == bounds->top && curbounds.left == bounds->left)
3056      flags |= SWP_NOMOVE;
3057   if ((curbounds.bottom - curbounds.top) == (bounds->bottom - bounds->top) &&
3058      (curbounds.right - curbounds.left) == (bounds->right - bounds->left))
3059      flags |= SWP_NOSIZE;
3060
3061   // if we need to, reposition the window
3062   if (flags != (SWP_NOMOVE | SWP_NOSIZE))
3063      SetWindowPos(wnd, NULL,
3064               bounds->left, bounds->top,
3065               bounds->right - bounds->left, bounds->bottom - bounds->top,
3066               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags);
3067}
3068
3069
3070
3071//============================================================
3072//  smart_show_window
3073//============================================================
3074
3075static void smart_show_window(HWND wnd, BOOL show)
3076{
3077   BOOL visible = IsWindowVisible(wnd);
3078   if ((visible && !show) || (!visible && show))
3079      ShowWindow(wnd, show ? SW_SHOW : SW_HIDE);
3080}
3081
3082
3083
3084//============================================================
3085//  smart_show_all
3086//============================================================
3087
3088static void smart_show_all(BOOL show)
3089{
3090   debugwin_info *info;
3091   if (!show)
3092      SetForegroundWindow(win_window_list->m_hwnd);
3093   for (info = window_list; info != NULL; info = info->next)
3094      smart_show_window(info->wnd, show);
3095}
3096261#else /* not windows */
3097   MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows")
262MODULE_NOT_SUPPORTED(debugger_windows, OSD_DEBUG_PROVIDER, "windows")
3098263#endif
3099264
3100265MODULE_DEFINITION(DEBUG_WINDOWS, debugger_windows)
trunk/src/osd/modules/debugger/win/consolewininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   consolewininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "consolewininfo.h"
10
11#include "debugviewinfo.h"
12#include "disasmviewinfo.h"
13#include "uimetrics.h"
14
15#include "debug/debugcon.h"
16#include "debug/debugcpu.h"
17#include "imagedev/cassette.h"
18
19#include "strconv.h"
20#include "winutf8.h"
21
22
23consolewin_info::consolewin_info(debugger_windows_interface &debugger) :
24   disasmbasewin_info(debugger, true, "Debug", NULL)
25{
26   if ((window() == NULL) || (m_views[0] == NULL))
27      goto cleanup;
28
29   // create the views
30   m_views[1].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_STATE)));
31   if (!m_views[1]->is_valid())
32      goto cleanup;
33   m_views[2].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_CONSOLE)));
34   if (!m_views[2]->is_valid())
35      goto cleanup;
36
37   {
38      // Add image menu only if image devices exist
39      image_interface_iterator iter(machine().root_device());
40      if (iter.first() != NULL)
41      {
42         //info->update_menu = image_update_menu;
43         //image_update_menu(info);
44      }
45
46      // get the work bounds
47      RECT work_bounds, bounds;
48      SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
49
50      // adjust the min/max sizes for the window style
51      bounds.top = bounds.left = 0;
52      bounds.right = bounds.bottom = EDGE_WIDTH + m_views[1]->maxwidth() + (2 * EDGE_WIDTH) + 100 + EDGE_WIDTH;
53      AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
54      set_minwidth(bounds.right - bounds.left);
55
56      bounds.top = bounds.left = 0;
57      bounds.right = bounds.bottom = EDGE_WIDTH + m_views[1]->maxwidth() + (2 * EDGE_WIDTH) + MAX(m_views[0]->maxwidth(), m_views[2]->maxwidth()) + EDGE_WIDTH;
58      AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
59      set_maxwidth(bounds.right - bounds.left);
60
61      // position the window at the bottom-right
62      int const bestwidth = MIN(maxwidth(), work_bounds.right - work_bounds.left);
63      int const bestheight = MIN(500, work_bounds.bottom - work_bounds.top);
64      SetWindowPos(window(), HWND_TOP,
65               work_bounds.right - bestwidth, work_bounds.bottom - bestheight,
66               bestwidth, bestheight,
67               SWP_SHOWWINDOW);
68   }
69
70   // recompute the children
71   set_cpu(*debug_cpu_get_visible_cpu(machine()));
72
73   // mark the edit box as the default focus and set it
74   set_default_focus();
75   return;
76
77cleanup:
78   m_views[2].reset();
79   m_views[1].reset();
80   m_views[0].reset();
81}
82
83
84consolewin_info::~consolewin_info()
85{
86}
87
88
89void consolewin_info::set_cpu(device_t &device)
90{
91   // first set all the views to the new cpu number
92   m_views[0]->set_source_for_device(device);
93   m_views[1]->set_source_for_device(device);
94
95   // then update the caption
96   char curtitle[256];
97   astring title;
98
99   title.printf("Debug: %s - %s '%s'", device.machine().system().name, device.name(), device.tag());
100   win_get_window_text_utf8(window(), curtitle, ARRAY_LENGTH(curtitle));
101   if (title.cmp(curtitle) != 0)
102      win_set_window_text_utf8(window(), title);
103
104   // and recompute the children
105   recompute_children();
106}
107
108
109void consolewin_info::recompute_children()
110{
111   // get the parent's dimensions
112   RECT parent;
113   GetClientRect(window(), &parent);
114
115   // registers always get their desired width, and span the entire height
116   RECT regrect;
117   regrect.top = parent.top + EDGE_WIDTH;
118   regrect.bottom = parent.bottom - EDGE_WIDTH;
119   regrect.left = parent.left + EDGE_WIDTH;
120   regrect.right = regrect.left + m_views[1]->maxwidth();
121
122   // edit box goes at the bottom of the remaining area
123   RECT editrect;
124   editrect.bottom = parent.bottom - EDGE_WIDTH;
125   editrect.top = editrect.bottom - metrics().debug_font_height() - 4;
126   editrect.left = regrect.right + (EDGE_WIDTH * 2);
127   editrect.right = parent.right - EDGE_WIDTH;
128
129   // console and disassembly split the difference
130   RECT disrect;
131   disrect.top = parent.top + EDGE_WIDTH;
132   disrect.bottom = ((editrect.top - parent.top) / 2) - EDGE_WIDTH;
133   disrect.left = regrect.right + (EDGE_WIDTH * 2);
134   disrect.right = parent.right - EDGE_WIDTH;
135
136   RECT conrect;
137   conrect.top = disrect.bottom + (EDGE_WIDTH * 2);
138   conrect.bottom = editrect.top - EDGE_WIDTH;
139   conrect.left = regrect.right + (EDGE_WIDTH * 2);
140   conrect.right = parent.right - EDGE_WIDTH;
141
142   // set the bounds of things
143   m_views[0]->set_bounds(disrect);
144   m_views[1]->set_bounds(regrect);
145   m_views[2]->set_bounds(conrect);
146   set_editwnd_bounds(editrect);
147}
148
149
150void consolewin_info::update_menu()
151{
152   disasmbasewin_info::update_menu();
153
154   image_interface_iterator iter(machine().root_device());
155   if (iter.first() != NULL)
156   {
157      DeleteMenu(GetMenu(window()), 2, MF_BYPOSITION);
158
159      // create the image menu
160      HMENU const devicesmenu = CreatePopupMenu();
161      device_image_interface *img;
162      UINT32 cnt;
163      for (img = iter.first(), cnt = 0; img != NULL; img = iter.next(), cnt++)
164      {
165         HMENU const devicesubmenu = CreatePopupMenu();
166
167         UINT_PTR const new_item = ID_DEVICE_OPTIONS + (cnt * DEVOPTION_MAX);
168
169         UINT flags_for_exists = MF_ENABLED | MF_STRING;
170         if (!img->exists())
171            flags_for_exists |= MF_GRAYED;
172
173         UINT flags_for_writing = flags_for_exists;
174         if (img->is_readonly())
175            flags_for_writing |= MF_GRAYED;
176
177         AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_OPEN, TEXT("Mount..."));
178
179         //if (img->is_creatable())
180            //AppendMenu(devicesubmenu, MF_STRING, new_item + DEVOPTION_CREATE, TEXT("Create..."));
181         AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CLOSE, TEXT("Unmount"));
182
183         if (img->device().type() == CASSETTE)
184         {
185            cassette_state const state = (cassette_state)(img->exists() ? (downcast<cassette_image_device *>(&img->device())->get_state() & CASSETTE_MASK_UISTATE) : CASSETTE_STOPPED);
186            AppendMenu(devicesubmenu, MF_SEPARATOR, 0, NULL);
187            AppendMenu(devicesubmenu, flags_for_exists | ((state == CASSETTE_STOPPED) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_STOPPAUSE, TEXT("Pause/Stop"));
188            AppendMenu(devicesubmenu, flags_for_exists | ((state == CASSETTE_PLAY) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_PLAY, TEXT("Play"));
189            AppendMenu(devicesubmenu, flags_for_writing | ((state == CASSETTE_RECORD) ? MF_CHECKED : 0), new_item + DEVOPTION_CASSETTE_RECORD, TEXT("Record"));
190            AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_REWIND, TEXT("Rewind"));
191            AppendMenu(devicesubmenu, flags_for_exists, new_item + DEVOPTION_CASSETTE_FASTFORWARD, TEXT("Fast Forward"));
192         }
193
194         astring temp;
195         temp.format("%s :%s", img->device().name(), img->exists() ? img->filename() : "[empty slot]");
196         TCHAR *tc_buf = tstring_from_utf8(temp);
197         if (tc_buf != NULL)
198         {
199            AppendMenu(devicesmenu, MF_ENABLED | MF_POPUP, (UINT_PTR)devicesubmenu, tc_buf);
200            osd_free(tc_buf);
201         }
202      }
203      AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)devicesmenu, TEXT("Images"));
204   }
205}
206
207
208bool consolewin_info::handle_command(WPARAM wparam, LPARAM lparam)
209{
210   if ((HIWORD(wparam) == 0) && (LOWORD(wparam) >= ID_DEVICE_OPTIONS))
211   {
212      UINT32 const devid = (LOWORD(wparam) - ID_DEVICE_OPTIONS) / DEVOPTION_MAX;
213      image_interface_iterator iter(machine().root_device());
214      device_image_interface *const img = iter.byindex(devid);
215      if (img != NULL)
216      {
217         switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
218         {
219         case DEVOPTION_OPEN :
220            {
221               astring filter;
222               build_generic_filter(img, false, filter);
223               LPTSTR t_filter = tstring_from_utf8(filter);
224               if (t_filter)
225               {
226                  // convert a pipe-char delimited string into a NUL delimited string
227                  for (int i = 0; t_filter[i] != '\0'; i++)
228                  {
229                     if (t_filter[i] == '|')
230                        t_filter[i] = '\0';
231                  }
232
233                  TCHAR selectedFilename[MAX_PATH];
234                  selectedFilename[0] = '\0';
235                  OPENFILENAME ofn;
236                  memset(&ofn, 0, sizeof(ofn));
237                  ofn.lStructSize = sizeof(ofn);
238                  ofn.hwndOwner = NULL;
239                  ofn.lpstrFile = selectedFilename;
240                  ofn.lpstrFile[0] = '\0';
241                  ofn.nMaxFile = MAX_PATH;
242                  ofn.lpstrFilter = t_filter;
243                  ofn.nFilterIndex = 1;
244                  ofn.lpstrFileTitle = NULL;
245                  ofn.nMaxFileTitle = 0;
246                  ofn.lpstrInitialDir = NULL;
247                  ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
248
249                  if (GetOpenFileName(&ofn))
250                  {
251                     char *utf8_buf = utf8_from_tstring(selectedFilename);
252                     if (utf8_buf != NULL)
253                     {
254                        img->load(utf8_buf);
255                        osd_free(utf8_buf);
256                     }
257                  }
258                  osd_free(t_filter);
259               }
260            }
261            return true;
262         //case DEVOPTION_CREATE:
263            //return true;
264         case DEVOPTION_CLOSE:
265            img->unload();
266            return 1;
267         }
268         if (img->device().type() == CASSETTE)
269         {
270            cassette_image_device *const cassette = downcast<cassette_image_device *>(&img->device());
271            switch ((LOWORD(wparam) - ID_DEVICE_OPTIONS) % DEVOPTION_MAX)
272            {
273            case DEVOPTION_CASSETTE_STOPPAUSE:
274               cassette->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
275               return true;
276            case DEVOPTION_CASSETTE_PLAY:
277               cassette->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
278               return true;
279            case DEVOPTION_CASSETTE_RECORD:
280               cassette->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
281               return true;
282            case DEVOPTION_CASSETTE_REWIND:
283               cassette->seek(-60.0, SEEK_CUR);
284               return true;
285            case DEVOPTION_CASSETTE_FASTFORWARD:
286               cassette->seek(+60.0, SEEK_CUR);
287               return true;
288            }
289         }
290      }
291   }
292   return disasmbasewin_info::handle_command(wparam, lparam);
293}
294
295
296void consolewin_info::process_string(char const *string)
297{
298   if (string[0] == 0)   // an empty string is a single step
299      debug_cpu_get_visible_cpu(machine())->debug()->single_step();
300   else            // otherwise, just process the command
301      debug_console_execute_command(machine(), string, 1);
302
303   // clear the edit text box
304   set_editwnd_text("");
305}
306
307
308void consolewin_info::build_generic_filter(device_image_interface *img, bool is_save, astring &filter)
309{
310   // common image types
311   add_filter_entry(filter, "Common image types", img->file_extensions());
312
313   // compressed
314   if (!is_save)
315      filter.cat("Compressed Images (*.zip)|*.zip|");
316
317   // all files
318   filter.cat("All files (*.*)|*.*|");
319}
320
321
322void consolewin_info::add_filter_entry(astring &dest, const char *description, const char *extensions)
323{
324   // add the description
325   dest.cat(description);
326   dest.catformat(" (");
327
328   // add the extensions to the description
329   copy_extension_list(dest, extensions);
330
331   // add the trailing rparen and '|' character
332   dest.cat(")|");
333
334   // now add the extension list itself
335   copy_extension_list(dest, extensions);
336
337   // append a '|'
338   dest.cat('|');
339}
340
341
342void consolewin_info::copy_extension_list(astring &dest, const char *extensions)
343{
344   // our extension lists are comma delimited; Win32 expects to see lists
345   // delimited by semicolons
346   char const *s = extensions;
347   while (*s)
348   {
349      // append a semicolon if not at the beginning
350      if (s != extensions)
351         dest.cat(';');
352
353      // append ".*"
354      dest.cat("*.");
355
356      // append the file extension
357      while (*s && (*s != ','))
358         dest.cat(*s++);
359
360      // if we found a comma, advance
361      while(*s == ',')
362         s++;
363   }
364}
trunk/src/osd/modules/debugger/win/consolewininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   consolewininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_CONSOLE_WIN_INFO_H__
10#define __DEBUG_WIN_CONSOLE_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "disasmbasewininfo.h"
15
16
17class consolewin_info : public disasmbasewin_info
18{
19public:
20   consolewin_info(debugger_windows_interface &debugger);
21   virtual ~consolewin_info();
22
23   void set_cpu(device_t &device);
24
25protected:
26   virtual void recompute_children();
27   virtual void update_menu();
28   virtual bool handle_command(WPARAM wparam, LPARAM lparam);
29
30private:
31   enum
32   {
33      DEVOPTION_OPEN,
34      DEVOPTION_CREATE,
35      DEVOPTION_CLOSE,
36      DEVOPTION_CASSETTE_STOPPAUSE,
37      DEVOPTION_CASSETTE_PLAY,
38      DEVOPTION_CASSETTE_RECORD,
39      DEVOPTION_CASSETTE_REWIND,
40      DEVOPTION_CASSETTE_FASTFORWARD,
41      DEVOPTION_MAX
42   };
43
44   virtual void process_string(char const *string);
45
46   static void build_generic_filter(device_image_interface *img, bool is_save, astring &filter);
47   static void add_filter_entry(astring &dest, char const *description, char const *extensions);
48   static void copy_extension_list(astring &dest, char const *extensions);
49};
50
51#endif
trunk/src/osd/modules/debugger/win/debugbaseinfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugbaseinfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "debugbaseinfo.h"
10
11
12debugbase_info::debugbase_info(debugger_windows_interface &debugger) :
13   m_debugger(debugger),
14   m_machine(debugger.machine()),
15   m_metrics(debugger.metrics()),
16   m_waiting_for_debugger(debugger.waiting_for_debugger())
17{
18}
19
20
21void debugbase_info::smart_set_window_bounds(HWND wnd, HWND parent, RECT const &bounds)
22{
23   RECT curbounds;
24   int flags = 0;
25
26   // first get the current bounds, relative to the parent
27   GetWindowRect(wnd, &curbounds);
28   if (parent != NULL)
29   {
30      RECT parentbounds;
31      GetWindowRect(parent, &parentbounds);
32      curbounds.top -= parentbounds.top;
33      curbounds.bottom -= parentbounds.top;
34      curbounds.left -= parentbounds.left;
35      curbounds.right -= parentbounds.left;
36   }
37
38   // if the position matches, don't change it
39   if (curbounds.top == bounds.top && curbounds.left == bounds.left)
40      flags |= SWP_NOMOVE;
41   if ((curbounds.bottom - curbounds.top) == (bounds.bottom - bounds.top) &&
42      (curbounds.right - curbounds.left) == (bounds.right - bounds.left))
43      flags |= SWP_NOSIZE;
44
45   // if we need to, reposition the window
46   if (flags != (SWP_NOMOVE | SWP_NOSIZE))
47      SetWindowPos(wnd, NULL,
48               bounds.left, bounds.top,
49               bounds.right - bounds.left, bounds.bottom - bounds.top,
50               SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | flags);
51}
52
53
54
55void debugbase_info::smart_show_window(HWND wnd, bool show)
56{
57   BOOL const visible = IsWindowVisible(wnd);
58   if ((visible && !show) || (!visible && show))
59      ShowWindow(wnd, show ? SW_SHOW : SW_HIDE);
60}
trunk/src/osd/modules/debugger/win/debugbaseinfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugbaseinfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DEBUG_BASE_INFO_H__
10#define __DEBUG_WIN_DEBUG_BASE_INFO_H__
11
12#include "debugwin.h"
13
14#include "emu.h"
15
16
17class debugbase_info
18{
19protected:
20   debugbase_info(debugger_windows_interface &debugger);
21
22   debugger_windows_interface &debugger() const { return m_debugger; }
23   running_machine &machine() const { return m_machine; }
24   ui_metrics const &metrics() const { return m_metrics; }
25
26   bool waiting_for_debugger() const { return m_waiting_for_debugger; }
27   bool seq_pressed() const { return m_debugger.seq_pressed(); }
28
29   static void smart_set_window_bounds(HWND wnd, HWND parent, RECT const &bounds);
30   static void smart_show_window(HWND wnd, bool show);
31
32private:
33   debugger_windows_interface   &m_debugger;
34   running_machine            &m_machine;
35   ui_metrics const         &m_metrics;
36   bool const               &m_waiting_for_debugger;
37};
38
39
40#endif
trunk/src/osd/modules/debugger/win/debugviewinfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugview.c - Win32 debug window handling
6//
7//============================================================
8
9#include "debugviewinfo.h"
10
11#include "debugwininfo.h"
12#include "uimetrics.h"
13
14#include "debug/debugcpu.h"
15
16#include "strconv.h"
17
18
19// debugger view styles
20#define   DEBUG_VIEW_STYLE   WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
21#define   DEBUG_VIEW_STYLE_EX   0
22
23// combo box styles
24#define   COMBO_BOX_STYLE      WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL
25#define   COMBO_BOX_STYLE_EX   0
26
27// horizontal scroll bar styles
28#define   HSCROLL_STYLE      WS_CHILD | WS_VISIBLE | SBS_HORZ
29#define   HSCROLL_STYLE_EX   0
30
31// vertical scroll bar styles
32#define   VSCROLL_STYLE      WS_CHILD | WS_VISIBLE | SBS_VERT
33#define   VSCROLL_STYLE_EX   0
34
35
36bool debugview_info::s_window_class_registered = false;
37
38
39debugview_info::debugview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent, debug_view_type type) :
40   debugbase_info(debugger),
41   m_owner(owner),
42   m_view(NULL),
43   m_wnd(NULL),
44   m_hscroll(NULL),
45   m_vscroll(NULL)
46{
47   register_window_class();
48
49   // create the child view
50   m_wnd = CreateWindowEx(DEBUG_VIEW_STYLE_EX, TEXT("MAMEDebugView"), NULL, DEBUG_VIEW_STYLE,
51         0, 0, 100, 100, parent, NULL, GetModuleHandle(NULL), this);
52   if (m_wnd == NULL)
53      goto cleanup;
54
55   // create the scroll bars
56   m_hscroll = CreateWindowEx(HSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, HSCROLL_STYLE,
57         0, 0, 100, CW_USEDEFAULT, m_wnd, NULL, GetModuleHandle(NULL), this);
58   m_vscroll = CreateWindowEx(VSCROLL_STYLE_EX, TEXT("SCROLLBAR"), NULL, VSCROLL_STYLE,
59         0, 0, CW_USEDEFAULT, 100, m_wnd, NULL, GetModuleHandle(NULL), this);
60   if ((m_hscroll == NULL) || (m_vscroll == NULL))
61      goto cleanup;
62
63   // create the debug view
64   m_view = machine().debug_view().alloc_view(type, &debugview_info::static_update, this);
65   if (m_view == NULL)
66      goto cleanup;
67
68   return;
69
70cleanup:
71   if (m_view != NULL)
72      machine().debug_view().free_view(*m_view);
73   m_view = NULL;
74   if (m_hscroll != NULL)
75      DestroyWindow(m_hscroll);
76   m_hscroll = NULL;
77   if (m_vscroll != NULL)
78      DestroyWindow(m_vscroll);
79   m_vscroll = NULL;
80   if (m_wnd != NULL)
81      DestroyWindow(m_wnd);
82   m_wnd = NULL;
83}
84
85
86debugview_info::~debugview_info()
87{
88   if (m_view)
89      machine().debug_view().free_view(*m_view);
90   if (m_wnd != NULL)
91      DestroyWindow(m_wnd);
92}
93
94
95bool debugview_info::is_valid() const
96{
97   return m_view && m_hscroll && m_vscroll && m_wnd;
98}
99
100
101UINT32 debugview_info::prefwidth() const
102{
103   return (m_view->total_size().x * metrics().debug_font_width()) + metrics().vscroll_width();
104}
105
106
107UINT32 debugview_info::maxwidth()
108{
109   UINT32 max = m_view->total_size().x;
110   debug_view_source const *const cursource = m_view->source();
111   for (debug_view_source const *source = m_view->first_source(); source != NULL; source = source->next())
112   {
113      m_view->set_source(*source);
114      UINT32 const chars = m_view->total_size().x;
115      if (max < chars)
116         max = chars;
117   }
118   if (cursource != NULL)
119      m_view->set_source(*cursource);
120   return (max * metrics().debug_font_width()) + metrics().vscroll_width();
121}
122
123
124void debugview_info::get_bounds(RECT &bounds) const
125{
126   GetWindowRect(m_wnd, &bounds);
127}
128
129
130void debugview_info::set_bounds(RECT const &newbounds)
131{
132   // account for the edges and set the bounds
133   if (m_wnd)
134      smart_set_window_bounds(m_wnd, GetParent(m_wnd), newbounds);
135
136   // update
137   update();
138}
139
140
141void debugview_info::send_vscroll(int delta)
142{
143   if (m_vscroll)
144   {
145      int message_type = SB_LINEUP;
146      if (delta < 0)
147      {
148         message_type = SB_LINEDOWN;
149         delta = -delta;
150      }
151      while (delta > 0)
152      {
153         SendMessage(m_wnd, WM_VSCROLL, message_type, (LPARAM)m_vscroll);
154         delta--;
155      }
156   }
157}
158
159
160void debugview_info::send_pageup()
161{
162   if (m_vscroll)
163   {
164      SendMessage(m_wnd, WM_VSCROLL, SB_PAGELEFT, (LPARAM)m_vscroll);
165   }
166}
167
168
169void debugview_info::send_pagedown()
170{
171   if (m_vscroll)
172   {
173      SendMessage(m_wnd, WM_VSCROLL, SB_PAGERIGHT, (LPARAM)m_vscroll);
174   }
175}
176
177
178char const *debugview_info::source_name() const
179{
180   if (m_view != NULL)
181   {
182      debug_view_source const *const source = m_view->source();
183      if (source != NULL)
184         return source->name();
185   }
186   return "";
187}
188
189
190device_t *debugview_info::source_device() const
191{
192   if (m_view != NULL)
193   {
194      debug_view_source const *const source = m_view->source();
195      if (source != NULL)
196         return source->device();
197   }
198   return NULL;
199}
200
201
202bool debugview_info::source_is_visible_cpu() const
203{
204   if (m_view != NULL)
205   {
206      const debug_view_source *const source = m_view->source();
207      return (source != NULL) && (debug_cpu_get_visible_cpu(machine()) == source->device());
208   }
209   return false;
210}
211
212
213bool debugview_info::set_source_index(int index)
214{
215   if (m_view != NULL)
216   {
217      const debug_view_source *const source = m_view->source_list().find(index);
218      if (source != NULL)
219      {
220         m_view->set_source(*source);
221         return true;
222      }
223   }
224   return false;
225}
226
227
228bool debugview_info::set_source_for_device(device_t &device)
229{
230   if (m_view != NULL)
231   {
232      const debug_view_source *const source = m_view->source_for_device(&device);
233      if (source != NULL)
234      {
235         m_view->set_source(*source);
236         return true;
237      }
238   }
239   return false;
240}
241
242
243bool debugview_info::set_source_for_visible_cpu()
244{
245   device_t *const curcpu = debug_cpu_get_visible_cpu(machine());
246   if (curcpu != NULL)
247      return set_source_for_device(*curcpu);
248   else
249      return false;
250}
251
252
253HWND debugview_info::create_source_combobox(HWND parent, LONG_PTR userdata)
254{
255   // create a combo box
256   HWND const result = CreateWindowEx(COMBO_BOX_STYLE_EX, TEXT("COMBOBOX"), NULL, COMBO_BOX_STYLE,
257         0, 0, 100, 1000, parent, NULL, GetModuleHandle(NULL), NULL);
258   SetWindowLongPtr(result, GWLP_USERDATA, userdata);
259   SendMessage(result, WM_SETFONT, (WPARAM)metrics().debug_font(), (LPARAM)FALSE);
260
261   // populate the combobox
262   debug_view_source const *const cursource = m_view->source();
263   int maxlength = 0;
264   for (debug_view_source const *source = m_view->first_source(); source != NULL; source = source->next())
265   {
266      int const length = strlen(source->name());
267      if (length > maxlength)
268         maxlength = length;
269      TCHAR *t_name = tstring_from_utf8(source->name());
270      SendMessage(result, CB_ADDSTRING, 0, (LPARAM)t_name);
271      osd_free(t_name);
272   }
273   if (cursource != NULL)
274   {
275      SendMessage(result, CB_SETCURSEL, m_view->source_list().indexof(*cursource), 0);
276      SendMessage(result, CB_SETDROPPEDWIDTH, ((maxlength + 2) * metrics().debug_font_width()) + metrics().vscroll_width(), 0);
277      m_view->set_source(*cursource);
278   }
279   return result;
280}
281
282
283void debugview_info::draw_contents(HDC windc)
284{
285   debug_view_char const *viewdata = m_view->viewdata();
286   debug_view_xy const visarea = m_view->visible_size();
287
288   // get the client rect
289   RECT client;
290   GetClientRect(m_wnd, &client);
291
292   // create a compatible DC and an offscreen bitmap
293   HDC const dc = CreateCompatibleDC(windc);
294   if (dc == NULL)
295      return;
296   HBITMAP const bitmap = CreateCompatibleBitmap(windc, client.right, client.bottom);
297   if (bitmap == NULL)
298   {
299      DeleteDC(dc);
300      return;
301   }
302   HGDIOBJ const oldbitmap = SelectObject(dc, bitmap);
303
304   // set the font
305   HGDIOBJ const oldfont = SelectObject(dc, metrics().debug_font());
306   COLORREF const oldfgcolor = GetTextColor(dc);
307   int const oldbkmode = GetBkMode(dc);
308   SetBkMode(dc, TRANSPARENT);
309
310   // iterate over rows and columns
311   for (UINT32 row = 0; row < visarea.y; row++)
312   {
313
314      // loop twice; once to fill the background and once to draw the text
315      for (int iter = 0; iter < 2; iter++)
316      {
317         COLORREF fgcolor = RGB(0x00,0x00,0x00);
318         COLORREF bgcolor = RGB(0xff,0xff,0xff);
319         HBRUSH bgbrush = NULL;
320         int last_attrib = -1;
321         TCHAR buffer[256];
322         int count = 0;
323         RECT bounds;
324
325         // initialize the text bounds
326         bounds.left = bounds.right = 0;
327         bounds.top = row * metrics().debug_font_height();
328         bounds.bottom = bounds.top + metrics().debug_font_height();
329
330         // start with a brush on iteration #0
331         if (iter == 0)
332            bgbrush = CreateSolidBrush(bgcolor);
333
334         // iterate over columns
335         for (UINT32 col = 0; col < visarea.x; col++)
336         {
337            // if the attribute changed, adjust the colors
338            if (viewdata[col].attrib != last_attrib)
339            {
340               COLORREF oldbg = bgcolor;
341
342               // reset to standard colors
343               fgcolor = RGB(0x00,0x00,0x00);
344               bgcolor = RGB(0xff,0xff,0xff);
345
346               // pick new fg/bg colors
347               if (viewdata[col].attrib & DCA_VISITED) bgcolor = RGB(0xc6, 0xe2, 0xff);
348               if (viewdata[col].attrib & DCA_ANCILLARY) bgcolor = RGB(0xe0,0xe0,0xe0);
349               if (viewdata[col].attrib & DCA_SELECTED) bgcolor = RGB(0xff,0x80,0x80);
350               if (viewdata[col].attrib & DCA_CURRENT) bgcolor = RGB(0xff,0xff,0x00);
351               if ((viewdata[col].attrib & DCA_SELECTED) && (viewdata[col].attrib & DCA_CURRENT)) bgcolor = RGB(0xff,0xc0,0x80);
352               if (viewdata[col].attrib & DCA_CHANGED) fgcolor = RGB(0xff,0x00,0x00);
353               if (viewdata[col].attrib & DCA_INVALID) fgcolor = RGB(0x00,0x00,0xff);
354               if (viewdata[col].attrib & DCA_DISABLED) fgcolor = RGB((GetRValue(fgcolor) + GetRValue(bgcolor)) / 2, (GetGValue(fgcolor) + GetGValue(bgcolor)) / 2, (GetBValue(fgcolor) + GetBValue(bgcolor)) / 2);
355               if (viewdata[col].attrib & DCA_COMMENT) fgcolor = RGB(0x00,0x80,0x00);
356
357               // flush any pending drawing
358               if (count > 0)
359               {
360                  bounds.right = bounds.left + (count * metrics().debug_font_width());
361                  if (iter == 0)
362                     FillRect(dc, &bounds, bgbrush);
363                  else
364                     ExtTextOut(dc, bounds.left, bounds.top, 0, NULL, buffer, count, NULL);
365                  bounds.left = bounds.right;
366                  count = 0;
367               }
368
369               // set the new colors
370               if (iter == 0 && oldbg != bgcolor)
371               {
372                  DeleteObject(bgbrush);
373                  bgbrush = CreateSolidBrush(bgcolor);
374               }
375               else if (iter == 1)
376                  SetTextColor(dc, fgcolor);
377               last_attrib = viewdata[col].attrib;
378            }
379
380            // add this character to the buffer
381            buffer[count++] = viewdata[col].byte;
382         }
383
384         // flush any remaining stuff
385         if (count > 0)
386         {
387            bounds.right = bounds.left + (count * metrics().debug_font_width());
388            if (iter == 0)
389               FillRect(dc, &bounds, bgbrush);
390            else
391               ExtTextOut(dc, bounds.left, bounds.top, 0, NULL, buffer, count, NULL);
392         }
393
394         // erase to the end of the line
395         if (iter == 0)
396         {
397            bounds.left = bounds.right;
398            bounds.right = client.right;
399            FillRect(dc, &bounds, bgbrush);
400            DeleteObject(bgbrush);
401         }
402      }
403
404      // advance viewdata
405      viewdata += visarea.x;
406   }
407
408   // erase anything beyond the bottom with white
409   GetClientRect(m_wnd, &client);
410   client.top = visarea.y * metrics().debug_font_height();
411   FillRect(dc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH));
412
413   // reset the font
414   SetBkMode(dc, oldbkmode);
415   SetTextColor(dc, oldfgcolor);
416   SelectObject(dc, oldfont);
417
418   // blit the final results
419   BitBlt(windc, 0, 0, client.right, client.bottom, dc, 0, 0, SRCCOPY);
420
421   // undo the offscreen stuff
422   SelectObject(dc, oldbitmap);
423   DeleteObject(bitmap);
424   DeleteDC(dc);
425}
426
427
428void debugview_info::update()
429{
430   RECT bounds, vscroll_bounds, hscroll_bounds;
431   debug_view_xy totalsize, visiblesize, topleft;
432   bool show_vscroll, show_hscroll;
433   SCROLLINFO scrollinfo;
434
435   // get the view window bounds
436   GetClientRect(m_wnd, &bounds);
437   visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width();
438   visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height();
439
440   // get the updated total rows/cols and left row/col
441   totalsize = m_view->total_size();
442   topleft = m_view->visible_position();
443
444   // determine if we need to show the scrollbars
445   show_vscroll = show_hscroll = false;
446   if (totalsize.x > visiblesize.x && bounds.bottom >= metrics().hscroll_height())
447   {
448      bounds.bottom -= metrics().hscroll_height();
449      visiblesize.y = (bounds.bottom - bounds.top) / metrics().debug_font_height();
450      show_hscroll = true;
451   }
452   if (totalsize.y > visiblesize.y && bounds.right >= metrics().vscroll_width())
453   {
454      bounds.right -= metrics().vscroll_width();
455      visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width();
456      show_vscroll = true;
457   }
458   if (!show_vscroll && totalsize.y > visiblesize.y && bounds.right >= metrics().vscroll_width())
459   {
460      bounds.right -= metrics().vscroll_width();
461      visiblesize.x = (bounds.right - bounds.left) / metrics().debug_font_width();
462      show_vscroll = true;
463   }
464
465   // compute the bounds of the scrollbars
466   GetClientRect(m_wnd, &vscroll_bounds);
467   vscroll_bounds.left = vscroll_bounds.right - metrics().vscroll_width();
468   if (show_hscroll)
469      vscroll_bounds.bottom -= metrics().hscroll_height();
470
471   GetClientRect(m_wnd, &hscroll_bounds);
472   hscroll_bounds.top = hscroll_bounds.bottom - metrics().hscroll_height();
473   if (show_vscroll)
474      hscroll_bounds.right -= metrics().vscroll_width();
475
476   // if we hid the scrollbars, make sure we reset the top/left corners
477   if (topleft.y + visiblesize.y > totalsize.y)
478      topleft.y = MAX(totalsize.y - visiblesize.y, 0);
479   if (topleft.x + visiblesize.x > totalsize.x)
480      topleft.x = MAX(totalsize.x - visiblesize.x, 0);
481
482   // fill out the scroll info struct for the vertical scrollbar
483   scrollinfo.cbSize = sizeof(scrollinfo);
484   scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
485   scrollinfo.nMin = 0;
486   scrollinfo.nMax = totalsize.y - 1;
487   scrollinfo.nPage = visiblesize.y;
488   scrollinfo.nPos = topleft.y;
489   SetScrollInfo(m_vscroll, SB_CTL, &scrollinfo, TRUE);
490
491   // fill out the scroll info struct for the horizontal scrollbar
492   scrollinfo.cbSize = sizeof(scrollinfo);
493   scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
494   scrollinfo.nMin = 0;
495   scrollinfo.nMax = totalsize.x - 1;
496   scrollinfo.nPage = visiblesize.x;
497   scrollinfo.nPos = topleft.x;
498   SetScrollInfo(m_hscroll, SB_CTL, &scrollinfo, TRUE);
499
500   // update window info
501   visiblesize.y++;
502   visiblesize.x++;
503   m_view->set_visible_size(visiblesize);
504   m_view->set_visible_position(topleft);
505
506   // invalidate the bounds
507   InvalidateRect(m_wnd, NULL, FALSE);
508
509   // adjust the bounds of the scrollbars and show/hide them
510   if (m_vscroll)
511   {
512      if (show_vscroll)
513         smart_set_window_bounds(m_vscroll, m_wnd, vscroll_bounds);
514      smart_show_window(m_vscroll, show_vscroll);
515   }
516   if (m_hscroll)
517   {
518      if (show_hscroll)
519         smart_set_window_bounds(m_hscroll, m_wnd, hscroll_bounds);
520      smart_show_window(m_hscroll, show_hscroll);
521   }
522}
523
524
525UINT32 debugview_info::process_scroll(WORD type, HWND wnd)
526{
527   // get the current info
528   SCROLLINFO scrollinfo;
529   scrollinfo.cbSize = sizeof(scrollinfo);
530   scrollinfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
531   GetScrollInfo(wnd, SB_CTL, &scrollinfo);
532
533   // by default we stay put
534   INT32 result = scrollinfo.nPos;
535
536   // determine the maximum value
537   INT32 const maxval = (scrollinfo.nMax > scrollinfo.nPage) ? (scrollinfo.nMax - scrollinfo.nPage + 1) : 0;
538
539   // handle the message
540   switch (type)
541   {
542   case SB_THUMBTRACK:
543      result = scrollinfo.nTrackPos;
544      break;
545
546   case SB_LEFT:
547      result = 0;
548      break;
549
550   case SB_RIGHT:
551      result = maxval;
552      break;
553
554   case SB_LINELEFT:
555      result -= 1;
556      break;
557
558   case SB_LINERIGHT:
559      result += 1;
560      break;
561
562   case SB_PAGELEFT:
563      result -= scrollinfo.nPage - 1;
564      break;
565
566   case SB_PAGERIGHT:
567      result += scrollinfo.nPage - 1;
568      break;
569   }
570
571   // generic rangecheck
572   if (result < 0)
573      result = 0;
574   if (result > maxval)
575      result = maxval;
576
577   // set the new position
578   scrollinfo.fMask = SIF_POS;
579   scrollinfo.nPos = result;
580   SetScrollInfo(wnd, SB_CTL, &scrollinfo, TRUE);
581
582   return (UINT32)result;
583}
584
585
586LRESULT debugview_info::view_proc(UINT message, WPARAM wparam, LPARAM lparam)
587{
588   // handle a few messages
589   switch (message)
590   {
591   // paint: redraw the last bitmap
592   case WM_PAINT:
593      {
594         PAINTSTRUCT pstruct;
595         HDC const dc = BeginPaint(m_wnd, &pstruct);
596         draw_contents(dc);
597         EndPaint(m_wnd, &pstruct);
598         break;
599      }
600
601   // keydown: handle debugger keys
602   case WM_SYSKEYDOWN:
603      if (wparam != VK_F10)
604         return DefWindowProc(m_wnd, message, wparam, lparam);
605         // (fall through)
606   case WM_KEYDOWN:
607      {
608         if (m_owner.handle_key(wparam, lparam))
609         {
610            m_owner.set_ignore_char_lparam(lparam);
611         }
612         else
613         {
614            switch (wparam)
615            {
616            case VK_UP:
617               m_view->process_char(DCH_UP);
618               m_owner.set_ignore_char_lparam(lparam);
619               break;
620
621            case VK_DOWN:
622               m_view->process_char(DCH_DOWN);
623               m_owner.set_ignore_char_lparam(lparam);
624               break;
625
626            case VK_LEFT:
627               if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
628                  m_view->process_char(DCH_CTRLLEFT);
629               else
630                  m_view->process_char(DCH_LEFT);
631               m_owner.set_ignore_char_lparam(lparam);
632               break;
633
634            case VK_RIGHT:
635               if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
636                  m_view->process_char(DCH_CTRLRIGHT);
637               else
638                  m_view->process_char(DCH_RIGHT);
639               m_owner.set_ignore_char_lparam(lparam);
640               break;
641
642            case VK_PRIOR:
643               m_view->process_char(DCH_PUP);
644               m_owner.set_ignore_char_lparam(lparam);
645               break;
646
647            case VK_NEXT:
648               m_view->process_char(DCH_PDOWN);
649               m_owner.set_ignore_char_lparam(lparam);
650               break;
651
652            case VK_HOME:
653               if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
654                  m_view->process_char(DCH_CTRLHOME);
655               else
656                  m_view->process_char(DCH_HOME);
657               m_owner.set_ignore_char_lparam(lparam);
658               break;
659
660            case VK_END:
661               if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
662                  m_view->process_char(DCH_CTRLEND);
663               else
664                  m_view->process_char(DCH_END);
665               m_owner.set_ignore_char_lparam(lparam);
666               break;
667
668            case VK_ESCAPE:
669               m_owner.set_default_focus();
670               m_owner.set_ignore_char_lparam(lparam);
671               break;
672
673            case VK_TAB:
674               if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
675                  m_owner.prev_view(this);
676               else
677                  m_owner.next_view(this);
678               m_owner.set_ignore_char_lparam(lparam);
679               break;
680            }
681         }
682         break;
683      }
684
685   // char: ignore chars associated with keys we've handled
686   case WM_CHAR:
687      if (m_owner.check_ignore_char_lparam(lparam))
688      {
689         if (waiting_for_debugger() || !seq_pressed())
690         {
691            if (wparam >= 32 && wparam < 127)
692            {
693               if (m_view->cursor_supported())
694                  m_view->set_cursor_visible(true);
695               m_view->process_char(wparam);
696            }
697            else
698            {
699               return DefWindowProc(m_wnd, message, wparam, lparam);
700            }
701         }
702      }
703      break;
704
705   // gaining focus
706   case WM_SETFOCUS:
707      if (m_view->cursor_supported())
708         m_view->set_cursor_visible(true);
709      break;
710
711   // losing focus
712   case WM_KILLFOCUS:
713      if (m_view->cursor_supported())
714         m_view->set_cursor_visible(false);
715      break;
716
717   // mouse click
718   case WM_LBUTTONDOWN:
719      {
720         debug_view_xy topleft = m_view->visible_position();
721         debug_view_xy newpos;
722         newpos.x = topleft.x + GET_X_LPARAM(lparam) / metrics().debug_font_width();
723         newpos.y = topleft.y + GET_Y_LPARAM(lparam) / metrics().debug_font_height();
724         m_view->process_click(DCK_LEFT_CLICK, newpos);
725         SetFocus(m_wnd);
726         break;
727      }
728
729   // hscroll
730   case WM_HSCROLL:
731      {
732         debug_view_xy topleft = m_view->visible_position();
733         topleft.x = process_scroll(LOWORD(wparam), (HWND)lparam);
734         m_view->set_visible_position(topleft);
735         machine().debug_view().flush_osd_updates();
736         break;
737      }
738
739   // vscroll
740   case WM_VSCROLL:
741      {
742         debug_view_xy topleft = m_view->visible_position();
743         topleft.y = process_scroll(LOWORD(wparam), (HWND)lparam);
744         m_view->set_visible_position(topleft);
745         machine().debug_view().flush_osd_updates();
746         break;
747      }
748
749   // everything else: defaults
750   default:
751      return DefWindowProc(m_wnd, message, wparam, lparam);
752   }
753
754   return 0;
755}
756
757
758void debugview_info::static_update(debug_view &view, void *osdprivate)
759{
760   debugview_info *const info = (debugview_info *)osdprivate;
761   assert(info->m_view == &view);
762   info->update();
763}
764
765
766LRESULT CALLBACK debugview_info::static_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
767{
768   if (message == WM_CREATE)
769   {
770      // set the info pointer
771      CREATESTRUCT const *const createinfo = (CREATESTRUCT *)lparam;
772      SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
773      return 0;
774   }
775
776   debugview_info *const info = (debugview_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
777   if (!info)
778      return DefWindowProc(wnd, message, wparam, lparam);
779
780   assert(info->m_wnd == wnd);
781   return info->view_proc(message, wparam, lparam);
782}
783
784
785void debugview_info::register_window_class()
786{
787   if (!s_window_class_registered)
788   {
789      WNDCLASS wc = { 0 };
790
791      // initialize the description of the window class
792      wc.lpszClassName   = TEXT("MAMEDebugView");
793      wc.hInstance      = GetModuleHandle(NULL);
794      wc.lpfnWndProc      = &debugview_info::static_view_proc;
795      wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
796      wc.hIcon         = LoadIcon(wc.hInstance, MAKEINTRESOURCE(2));
797      wc.lpszMenuName      = NULL;
798      wc.hbrBackground   = NULL;
799      wc.style         = 0;
800      wc.cbClsExtra      = 0;
801      wc.cbWndExtra      = 0;
802
803      // register the class; fail if we can't
804      if (!RegisterClass(&wc))
805         fatalerror("Unable to register debug view class\n");
806
807      s_window_class_registered = true;
808   }
809}
trunk/src/osd/modules/debugger/win/debugviewinfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugviewinfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DEBUG_VIEW_INFO_H__
10#define __DEBUG_WIN_DEBUG_VIEW_INFO_H__
11
12#include "debugwin.h"
13
14#include "debugbaseinfo.h"
15
16#include "emu.h"
17#include "debug/debugvw.h"
18
19
20class debugview_info : protected debugbase_info
21{
22public:
23   debugview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent, debug_view_type type);
24   virtual ~debugview_info();
25
26   bool is_valid() const;
27
28   bool owns_window(HWND wnd) const { return m_wnd == wnd; }
29
30   UINT32 prefwidth() const;
31   UINT32 maxwidth();
32   void get_bounds(RECT &bounds) const;
33   void set_bounds(RECT const &newbounds);
34
35   void send_vscroll(int delta);
36   void send_pageup();
37   void send_pagedown();
38   void set_focus() { SetFocus(m_wnd); }
39
40   debug_view_xy total_size() const { return m_view->total_size(); }
41   bool cursor_supported() const { return m_view->cursor_supported(); }
42   bool cursor_visible() const { return m_view->cursor_visible(); }
43
44   char const *source_name() const;
45   device_t *source_device() const;
46   bool source_is_visible_cpu() const;
47   bool set_source_index(int index);
48   bool set_source_for_device(device_t &device);
49   bool set_source_for_visible_cpu();
50
51   HWND create_source_combobox(HWND parent, LONG_PTR userdata);
52
53protected:
54   template <typename T> T *view() const { return downcast<T *>(m_view); }
55
56private:
57   void draw_contents(HDC windc);
58   void update();
59   UINT32 process_scroll(WORD type, HWND wnd);
60   LRESULT view_proc(UINT message, WPARAM wparam, LPARAM lparam);
61
62   static void static_update(debug_view &view, void *osdprivate);
63   static LRESULT CALLBACK static_view_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
64
65   static void register_window_class();
66
67   debugwin_info   &m_owner;
68   debug_view      *m_view;
69   HWND         m_wnd;
70   HWND         m_hscroll;
71   HWND         m_vscroll;
72
73   static bool      s_window_class_registered;
74};
75
76#endif
trunk/src/osd/modules/debugger/win/debugwin.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugwin.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DEBUG_WIN_H__
10#define __DEBUG_WIN_DEBUG_WIN_H__
11
12// standard windows headers
13#define WIN32_LEAN_AND_MEAN
14#include <windows.h>
15#include <windowsx.h>
16#include <tchar.h>
17#include <commdlg.h>
18#ifdef _MSC_VER
19#include <zmouse.h>
20#endif
21
22#include "emu.h"
23
24
25class debugview_info;
26class debugwin_info;
27class ui_metrics;
28
29
30class debugger_windows_interface
31{
32public:
33   virtual ~debugger_windows_interface() { }
34
35   virtual running_machine &machine() const = 0;
36
37   virtual ui_metrics &metrics() const = 0;
38
39   virtual bool const &waiting_for_debugger() const = 0;
40   virtual bool seq_pressed() const = 0;
41
42   virtual void create_memory_window() = 0;
43   virtual void create_disasm_window() = 0;
44   virtual void create_log_window() = 0;
45   virtual void remove_window(debugwin_info &info) = 0;
46
47   virtual void show_all() = 0;
48   virtual void hide_all() = 0;
49};
50
51#endif
trunk/src/osd/modules/debugger/win/debugwininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugwininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "debugwininfo.h"
10
11#include "debugviewinfo.h"
12
13#include "debug/debugcpu.h"
14#include "imagedev/cassette.h"
15
16#include "strconv.h"
17#include "window.h"
18#include "winutf8.h"
19
20
21bool debugwin_info::s_window_class_registered = false;
22
23
24debugwin_info::debugwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
25   debugbase_info(debugger),
26   m_is_main_console(is_main_console),
27   m_next(NULL),
28   m_wnd(NULL),
29   m_handler(handler),
30   m_minwidth(200),
31   m_maxwidth(0),
32   m_minheight(200),
33   m_maxheight(0),
34   m_ignore_char_lparam(0)
35{
36   register_window_class();
37
38   m_wnd = win_create_window_ex_utf8(DEBUG_WINDOW_STYLE_EX, "MAMEDebugWindow", title, DEBUG_WINDOW_STYLE,
39         0, 0, 100, 100, win_window_list->m_hwnd, create_standard_menubar(), GetModuleHandle(NULL), this);
40   if (m_wnd == NULL)
41      return;
42
43   RECT work_bounds;
44   SystemParametersInfo(SPI_GETWORKAREA, 0, &work_bounds, 0);
45   m_maxwidth = work_bounds.right - work_bounds.left;
46   m_maxheight = work_bounds.bottom - work_bounds.top;
47}
48
49
50debugwin_info::~debugwin_info()
51{
52}
53
54
55void debugwin_info::destroy()
56{
57   for (int curview = 0; curview < MAX_VIEWS; curview++)
58      m_views[curview].reset();
59   DestroyWindow(m_wnd);
60}
61
62bool debugwin_info::set_default_focus()
63{
64   return false;
65}
66
67
68void debugwin_info::prev_view(debugview_info *curview)
69{
70   // count the number of views
71   int numviews;
72   for (numviews = 0; numviews < MAX_VIEWS; numviews++)
73   {
74      if (m_views[numviews] == NULL)
75         break;
76   }
77
78   // if we have a curview, find out its index
79   int curindex = 1;
80   if (curview)
81   {
82      for (curindex = numviews - 1; curindex > 0; curindex--)
83      {
84         if (m_views[curindex] == curview)
85            break;
86      }
87      if (curindex < 0)
88         curindex = 1;
89   }
90
91   // loop until we find someone to take focus
92   while (1)
93   {
94      // advance to the previous index
95      curindex--;
96      if (curindex < -1)
97         curindex = numviews - 1;
98
99      if (curindex < 0 && set_default_focus())
100      {
101         // negative numbers mean the focuswnd
102         break;
103      }
104      else if (curindex >= 0 && m_views[curindex] != NULL && m_views[curindex]->cursor_supported())
105      {
106         // positive numbers mean a view
107         m_views[curindex]->set_focus();
108         break;
109      }
110   }
111}
112
113
114void debugwin_info::next_view(debugview_info *curview)
115{
116   // count the number of views
117   int numviews;
118   for (numviews = 0; numviews < MAX_VIEWS; numviews++)
119   {
120      if (m_views[numviews] == NULL)
121         break;
122   }
123
124   // if we have a curview, find out its index
125   int curindex = -1;
126   if (curview)
127   {
128      for (curindex = numviews - 1; curindex > 0; curindex--)
129      {
130         if (m_views[curindex] == curview)
131            break;
132      }
133   }
134
135   // loop until we find someone to take focus
136   while (1)
137   {
138      // advance to the previous index
139      curindex++;
140      if (curindex >= numviews)
141         curindex = -1;
142
143      if (curindex < 0 && set_default_focus())
144      {
145         // negative numbers mean the focuswnd
146         break;
147      }
148      else if (curindex >= 0 && m_views[curindex] != NULL && m_views[curindex]->cursor_supported())
149      {
150         // positive numbers mean a view
151         m_views[curindex]->set_focus();
152         break;
153      }
154   }
155}
156
157
158bool debugwin_info::handle_key(WPARAM wparam, LPARAM lparam)
159{
160   /* ignore any keys that are received while the debug key is down */
161   if (!waiting_for_debugger() && seq_pressed())
162      return true;
163
164   switch (wparam)
165   {
166   case VK_F3:
167      if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
168         SendMessage(m_wnd, WM_COMMAND, ID_HARD_RESET, 0);
169      else
170         SendMessage(m_wnd, WM_COMMAND, ID_SOFT_RESET, 0);
171      return true;
172
173   case VK_F4:
174      if (GetAsyncKeyState(VK_MENU) & 0x8000)
175      {
176         /* ajg - never gets here since 'alt' seems to be captured somewhere else - menu maybe? */
177         SendMessage(m_wnd, WM_COMMAND, ID_EXIT, 0);
178         return true;
179      }
180      break;
181
182   case VK_F5:
183      SendMessage(m_wnd, WM_COMMAND, ID_RUN, 0);
184      return true;
185
186   case VK_F6:
187      SendMessage(m_wnd, WM_COMMAND, ID_NEXT_CPU, 0);
188      return true;
189
190   case VK_F7:
191      SendMessage(m_wnd, WM_COMMAND, ID_RUN_IRQ, 0);
192      return true;
193
194   case VK_F8:
195      SendMessage(m_wnd, WM_COMMAND, ID_RUN_VBLANK, 0);
196      return true;
197
198   case VK_F10:
199      SendMessage(m_wnd, WM_COMMAND, ID_STEP_OVER, 0);
200      return true;
201
202   case VK_F11:
203      if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
204         SendMessage(m_wnd, WM_COMMAND, ID_STEP_OUT, 0);
205      else
206         SendMessage(m_wnd, WM_COMMAND, ID_STEP, 0);
207      return true;
208
209   case VK_F12:
210      SendMessage(m_wnd, WM_COMMAND, ID_RUN_AND_HIDE, 0);
211      return true;
212
213   case 'M':
214      if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
215      {
216         SendMessage(m_wnd, WM_COMMAND, ID_NEW_MEMORY_WND, 0);
217         return true;
218      }
219      break;
220
221   case 'D':
222      if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
223      {
224         SendMessage(m_wnd, WM_COMMAND, ID_NEW_DISASM_WND, 0);
225         return true;
226      }
227      break;
228
229   case 'L':
230      if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
231      {
232         SendMessage(m_wnd, WM_COMMAND, ID_NEW_LOG_WND, 0);
233         return true;
234      }
235      break;
236   }
237
238   return false;
239}
240
241
242bool debugwin_info::handle_command(WPARAM wparam, LPARAM lparam)
243{
244   if (HIWORD(wparam) == 0)
245   {
246      switch (LOWORD(wparam))
247      {
248      case ID_NEW_MEMORY_WND:
249         debugger().create_memory_window();
250         return true;
251
252      case ID_NEW_DISASM_WND:
253         debugger().create_disasm_window();
254         return true;
255
256      case ID_NEW_LOG_WND:
257         debugger().create_log_window();
258         return true;
259
260      case ID_RUN_AND_HIDE:
261         debugger().hide_all();
262      case ID_RUN:
263         debug_cpu_get_visible_cpu(machine())->debug()->go();
264         return true;
265
266      case ID_NEXT_CPU:
267         debug_cpu_get_visible_cpu(machine())->debug()->go_next_device();
268         return true;
269
270      case ID_RUN_VBLANK:
271         debug_cpu_get_visible_cpu(machine())->debug()->go_vblank();
272         return true;
273
274      case ID_RUN_IRQ:
275         debug_cpu_get_visible_cpu(machine())->debug()->go_interrupt();
276         return true;
277
278      case ID_STEP:
279         debug_cpu_get_visible_cpu(machine())->debug()->single_step();
280         return true;
281
282      case ID_STEP_OVER:
283         debug_cpu_get_visible_cpu(machine())->debug()->single_step_over();
284         return true;
285
286      case ID_STEP_OUT:
287         debug_cpu_get_visible_cpu(machine())->debug()->single_step_out();
288         return true;
289
290      case ID_HARD_RESET:
291         machine().schedule_hard_reset();
292         return true;
293
294      case ID_SOFT_RESET:
295         machine().schedule_soft_reset();
296         debug_cpu_get_visible_cpu(machine())->debug()->go();
297         return true;
298
299      case ID_EXIT:
300         set_default_focus();
301         machine().schedule_exit();
302         return true;
303      }
304   }
305   return false;
306}
307
308
309void debugwin_info::draw_contents(HDC dc)
310{
311   // fill the background with light gray
312   RECT parent;
313   GetClientRect(m_wnd, &parent);
314   FillRect(dc, &parent, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
315
316   // draw edges around all views
317   for (int curview = 0; curview < MAX_VIEWS; curview++)
318   {
319      if (m_views[curview] != NULL)
320      {
321         RECT bounds;
322         m_views[curview]->get_bounds(bounds);
323         draw_border(dc, bounds);
324      }
325   }
326}
327
328
329void debugwin_info::draw_border(HDC dc, RECT &bounds)
330{
331   ScreenToClient(m_wnd, &((POINT *)&bounds)[0]);
332   ScreenToClient(m_wnd, &((POINT *)&bounds)[1]);
333   InflateRect(&bounds, EDGE_WIDTH, EDGE_WIDTH);
334   DrawEdge(dc, &bounds, EDGE_SUNKEN, BF_RECT);
335}
336
337
338void debugwin_info::draw_border(HDC dc, HWND child)
339{
340   RECT bounds;
341   GetWindowRect(child, &bounds);
342   draw_border(dc, bounds);
343}
344
345
346LRESULT debugwin_info::window_proc(UINT message, WPARAM wparam, LPARAM lparam)
347{
348   // handle a few messages
349   switch (message)
350   {
351   // paint: draw bezels as necessary
352   case WM_PAINT:
353      {
354         PAINTSTRUCT pstruct;
355         HDC dc = BeginPaint(m_wnd, &pstruct);
356         draw_contents(dc);
357         EndPaint(m_wnd, &pstruct);
358         break;
359      }
360
361   // keydown: handle debugger keys
362   case WM_KEYDOWN:
363      if (handle_key(wparam, lparam))
364         set_ignore_char_lparam(lparam);
365      break;
366
367   // char: ignore chars associated with keys we've handled
368   case WM_CHAR:
369      if (check_ignore_char_lparam(lparam))
370      {
371         if (waiting_for_debugger() || !seq_pressed())
372            return DefWindowProc(m_wnd, message, wparam, lparam);
373      }
374      break;
375
376   // activate: set the focus
377   case WM_ACTIVATE:
378      if (wparam != WA_INACTIVE)
379         set_default_focus();
380      break;
381
382   // get min/max info: set the minimum window size
383   case WM_GETMINMAXINFO:
384      {
385         MINMAXINFO *minmax = (MINMAXINFO *)lparam;
386         minmax->ptMinTrackSize.x = m_minwidth;
387         minmax->ptMinTrackSize.y = m_minheight;
388         minmax->ptMaxSize.x = minmax->ptMaxTrackSize.x = m_maxwidth;
389         minmax->ptMaxSize.y = minmax->ptMaxTrackSize.y = m_maxheight;
390         break;
391      }
392
393   // sizing: recompute child window locations
394   case WM_SIZE:
395   case WM_SIZING:
396      recompute_children();
397      InvalidateRect(m_wnd, NULL, FALSE);
398      break;
399
400   // mouse wheel: forward to the first view
401   case WM_MOUSEWHEEL:
402      {
403         static int units_carryover = 0;
404
405         UINT lines_per_click;
406         if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &lines_per_click, 0))
407            lines_per_click = 3;
408
409         int const units = GET_WHEEL_DELTA_WPARAM(wparam) + units_carryover;
410         int const clicks = units / WHEEL_DELTA;
411         units_carryover = units % WHEEL_DELTA;
412
413         int const delta = clicks * lines_per_click;
414         int viewnum = 0;
415         POINT point;
416
417         // figure out which view we are hovering over
418         GetCursorPos(&point);
419         ScreenToClient(m_wnd, &point);
420         HWND const child = ChildWindowFromPoint(m_wnd, point);
421         if (child)
422         {
423            for (viewnum = 0; viewnum < MAX_VIEWS; viewnum++)
424            {
425               if ((m_views[viewnum] != NULL) && m_views[viewnum]->owns_window(child))
426                  break;
427            }
428            if (viewnum == MAX_VIEWS)
429               break;
430         }
431
432         // send the appropriate message to this view's scrollbar
433         if (m_views[viewnum] != NULL)
434            m_views[viewnum]->send_vscroll(delta);
435
436         break;
437      }
438
439   // activate: set the focus
440   case WM_INITMENU:
441      update_menu();
442      break;
443
444   // command: handle a comment
445   case WM_COMMAND:
446      if (!handle_command(wparam, lparam))
447         return DefWindowProc(m_wnd, message, wparam, lparam);
448      break;
449
450   // close: close the window if it's not the main console
451   case WM_CLOSE:
452      if (m_is_main_console)
453      {
454         debugger().hide_all();
455         debug_cpu_get_visible_cpu(machine())->debug()->go();
456      }
457      else
458      {
459         destroy();
460      }
461      break;
462
463   // destroy: close down the window
464   case WM_NCDESTROY:
465      m_wnd = NULL;
466      debugger().remove_window(*this);
467      break;
468
469   // everything else: defaults
470   default:
471      return DefWindowProc(m_wnd, message, wparam, lparam);
472   }
473
474   return 0;
475}
476
477
478HMENU debugwin_info::create_standard_menubar()
479{
480   // create the debug menu
481   HMENU const debugmenu = CreatePopupMenu();
482   if (debugmenu == NULL)
483      return NULL;
484   AppendMenu(debugmenu, MF_ENABLED, ID_NEW_MEMORY_WND, TEXT("New Memory Window\tCtrl+M"));
485   AppendMenu(debugmenu, MF_ENABLED, ID_NEW_DISASM_WND, TEXT("New Disassembly Window\tCtrl+D"));
486   AppendMenu(debugmenu, MF_ENABLED, ID_NEW_LOG_WND, TEXT("New Error Log Window\tCtrl+L"));
487   AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
488   AppendMenu(debugmenu, MF_ENABLED, ID_RUN, TEXT("Run\tF5"));
489   AppendMenu(debugmenu, MF_ENABLED, ID_RUN_AND_HIDE, TEXT("Run and Hide Debugger\tF12"));
490   AppendMenu(debugmenu, MF_ENABLED, ID_NEXT_CPU, TEXT("Run to Next CPU\tF6"));
491   AppendMenu(debugmenu, MF_ENABLED, ID_RUN_IRQ, TEXT("Run until Next Interrupt on This CPU\tF7"));
492   AppendMenu(debugmenu, MF_ENABLED, ID_RUN_VBLANK, TEXT("Run until Next VBLANK\tF8"));
493   AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
494   AppendMenu(debugmenu, MF_ENABLED, ID_STEP, TEXT("Step Into\tF11"));
495   AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OVER, TEXT("Step Over\tF10"));
496   AppendMenu(debugmenu, MF_ENABLED, ID_STEP_OUT, TEXT("Step Out\tShift+F11"));
497   AppendMenu(debugmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
498   AppendMenu(debugmenu, MF_ENABLED, ID_SOFT_RESET, TEXT("Soft Reset\tF3"));
499   AppendMenu(debugmenu, MF_ENABLED, ID_HARD_RESET, TEXT("Hard Reset\tShift+F3"));
500   AppendMenu(debugmenu, MF_ENABLED, ID_EXIT, TEXT("Exit"));
501
502   // create the menu bar
503   HMENU const menubar = CreateMenu();
504   if (menubar == NULL)
505   {
506      DestroyMenu(debugmenu);
507      return NULL;
508   }
509   AppendMenu(menubar, MF_ENABLED | MF_POPUP, (UINT_PTR)debugmenu, TEXT("Debug"));
510
511   return menubar;
512}
513
514
515LRESULT CALLBACK debugwin_info::static_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
516{
517   if (message == WM_CREATE)
518   {
519      // set the info pointer
520      CREATESTRUCT const *const createinfo = (CREATESTRUCT *)lparam;
521      debugwin_info *const info = (debugwin_info *)createinfo->lpCreateParams;
522      SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)createinfo->lpCreateParams);
523      if (info->m_handler)
524         SetWindowLongPtr(wnd, GWLP_WNDPROC, (LONG_PTR)info->m_handler);
525      return 0;
526   }
527
528   debugwin_info *const info = (debugwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
529   if (!info)
530      return DefWindowProc(wnd, message, wparam, lparam);
531
532   assert(info->m_wnd == wnd);
533   return info->window_proc(message, wparam, lparam);
534}
535
536
537void debugwin_info::register_window_class()
538{
539   if (!s_window_class_registered)
540   {
541      WNDCLASS wc = { 0 };
542
543      // initialize the description of the window class
544      wc.lpszClassName   = TEXT("MAMEDebugWindow");
545      wc.hInstance      = GetModuleHandle(NULL);
546      wc.lpfnWndProc      = &debugwin_info::static_window_proc;
547      wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
548      wc.hIcon         = LoadIcon(wc.hInstance, MAKEINTRESOURCE(2));
549      wc.lpszMenuName      = NULL;
550      wc.hbrBackground   = NULL;
551      wc.style         = 0;
552      wc.cbClsExtra      = 0;
553      wc.cbWndExtra      = 0;
554
555      // register the class; fail if we can't
556      if (!RegisterClass(&wc))
557         fatalerror("Unable to register debug window class\n");
558
559      s_window_class_registered = true;
560   }
561}
trunk/src/osd/modules/debugger/win/debugwininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   debugwininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DEBUG_WIN_INFO_H__
10#define __DEBUG_WIN_DEBUG_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "debugbaseinfo.h"
15
16#include "emu.h"
17
18
19class debugwin_info : protected debugbase_info
20{
21public:
22   template<class U> friend class simple_list;
23
24   debugwin_info(debugger_windows_interface &debugger, bool main_console, LPCSTR title, WNDPROC handler);
25   virtual ~debugwin_info();
26
27   bool is_valid() const { return m_wnd != NULL; }
28   debugwin_info *next() const { return m_next; }
29
30   void set_ignore_char_lparam(LPARAM value) { m_ignore_char_lparam = value >> 16; }
31   bool check_ignore_char_lparam(LPARAM value)
32   {
33      if (m_ignore_char_lparam == (value >> 16))
34      {
35         m_ignore_char_lparam = 0;
36         return false;
37      }
38      else
39      {
40         return true;
41      }
42   }
43
44   void show() { smart_show_window(m_wnd, true); }
45   void hide() { smart_show_window(m_wnd, false); }
46   void set_foreground() { SetForegroundWindow(m_wnd); }
47   void destroy();
48
49   virtual bool set_default_focus();
50   void prev_view(debugview_info *curview);
51   void next_view(debugview_info *curview);
52   virtual bool restore_field(HWND wnd) { return false; }
53
54   virtual bool handle_key(WPARAM wparam, LPARAM lparam);
55
56protected:
57   static DWORD const   DEBUG_WINDOW_STYLE = (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & (~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX);
58   static DWORD const   DEBUG_WINDOW_STYLE_EX = 0;
59
60   static int const   MAX_VIEWS = 4;
61   static int const   EDGE_WIDTH = 3;
62
63   enum
64   {
65      ID_NEW_MEMORY_WND = 1,
66      ID_NEW_DISASM_WND,
67      ID_NEW_LOG_WND,
68      ID_RUN,
69      ID_RUN_AND_HIDE,
70      ID_RUN_VBLANK,
71      ID_RUN_IRQ,
72      ID_NEXT_CPU,
73      ID_STEP,
74      ID_STEP_OVER,
75      ID_STEP_OUT,
76      ID_HARD_RESET,
77      ID_SOFT_RESET,
78      ID_EXIT,
79
80      ID_1_BYTE_CHUNKS,
81      ID_2_BYTE_CHUNKS,
82      ID_4_BYTE_CHUNKS,
83      ID_8_BYTE_CHUNKS,
84      ID_LOGICAL_ADDRESSES,
85      ID_PHYSICAL_ADDRESSES,
86      ID_REVERSE_VIEW,
87      ID_INCREASE_MEM_WIDTH,
88      ID_DECREASE_MEM_WIDTH,
89
90      ID_SHOW_RAW,
91      ID_SHOW_ENCRYPTED,
92      ID_SHOW_COMMENTS,
93      ID_RUN_TO_CURSOR,
94      ID_TOGGLE_BREAKPOINT,
95
96      ID_DEVICE_OPTIONS   // keep this always at the end
97   };
98
99   HWND window() const { return m_wnd; }
100   UINT32 minwidth() const { return m_minwidth; }
101   UINT32 maxwidth() const { return m_maxwidth; }
102   void set_minwidth(UINT32 value) { m_minwidth = value; }
103   void set_maxwidth(UINT32 value) { m_maxwidth = value; }
104
105   virtual void recompute_children() = 0;
106   virtual void update_menu() { }
107   virtual bool handle_command(WPARAM wparam, LPARAM lparam);
108   virtual void draw_contents(HDC dc);
109   void draw_border(HDC dc, RECT &bounds);
110   void draw_border(HDC dc, HWND child);
111
112   auto_pointer<debugview_info>   m_views[MAX_VIEWS];
113
114private:
115   LRESULT window_proc(UINT message, WPARAM wparam, LPARAM lparam);
116
117   HMENU create_standard_menubar();
118
119   static LRESULT CALLBACK static_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
120
121   static void register_window_class();
122
123   bool const      m_is_main_console;
124
125   debugwin_info   *m_next;
126   HWND         m_wnd;
127   WNDPROC const   m_handler;
128
129   UINT32         m_minwidth, m_maxwidth;
130   UINT32         m_minheight, m_maxheight;
131
132   UINT16         m_ignore_char_lparam;
133
134   static bool      s_window_class_registered;
135};
136
137#endif
trunk/src/osd/modules/debugger/win/disasmbasewininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   disasmbasewininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "disasmbasewininfo.h"
10
11#include "debugviewinfo.h"
12#include "disasmviewinfo.h"
13
14#include "debugger.h"
15#include "debug/debugcon.h"
16#include "debug/debugcpu.h"
17
18//#include "winutf8.h"
19
20
21disasmbasewin_info::disasmbasewin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
22   editwin_info(debugger, is_main_console, title, handler)
23{
24   if (!window())
25      return;
26
27   m_views[0].reset(global_alloc(disasmview_info(debugger, *this, window())));
28   if ((m_views[0] == NULL) || !m_views[0]->is_valid())
29   {
30      m_views[0].reset();
31      return;
32   }
33
34   // create the options menu
35   HMENU const optionsmenu = CreatePopupMenu();
36   AppendMenu(optionsmenu, MF_ENABLED, ID_TOGGLE_BREAKPOINT, TEXT("Toggle breakpoint at cursor\tF9"));
37   AppendMenu(optionsmenu, MF_ENABLED, ID_RUN_TO_CURSOR, TEXT("Run to cursor\tF4"));
38   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
39   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_RAW, TEXT("Raw opcodes\tCtrl+R"));
40   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_ENCRYPTED, TEXT("Encrypted opcodes\tCtrl+E"));
41   AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_COMMENTS, TEXT("Comments\tCtrl+M"));
42   AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
43
44   // set up the view to track the initial expression
45   downcast<disasmview_info *>(m_views[0].get())->set_expression("curpc");
46   m_views[0]->set_source_for_visible_cpu();
47}
48
49
50disasmbasewin_info::~disasmbasewin_info()
51{
52}
53
54
55bool disasmbasewin_info::handle_key(WPARAM wparam, LPARAM lparam)
56{
57   if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
58   {
59      switch (wparam)
60      {
61      case 'R':
62         SendMessage(window(), WM_COMMAND, ID_SHOW_RAW, 0);
63         return 1;
64
65      case 'E':
66         SendMessage(window(), WM_COMMAND, ID_SHOW_ENCRYPTED, 0);
67         return 1;
68
69      case 'N':
70         SendMessage(window(), WM_COMMAND, ID_SHOW_COMMENTS, 0);
71         return 1;
72      }
73   }
74
75   switch (wparam)
76   {
77   /* ajg - steals the F4 from the global key handler - but ALT+F4 didn't work anyways ;) */
78   case VK_F4:
79      SendMessage(window(), WM_COMMAND, ID_RUN_TO_CURSOR, 0);
80      return 1;
81
82   case VK_F9:
83      SendMessage(window(), WM_COMMAND, ID_TOGGLE_BREAKPOINT, 0);
84      return 1;
85
86   case VK_RETURN:
87      if (m_views[0]->cursor_visible())
88      {
89         SendMessage(window(), WM_COMMAND, ID_STEP, 0);
90         return 1;
91      }
92      break;
93   }
94
95   return editwin_info::handle_key(wparam, lparam);
96}
97
98
99void disasmbasewin_info::update_menu()
100{
101   editwin_info::update_menu();
102
103   HMENU const menu = GetMenu(window());
104
105   bool const disasm_cursor_visible = m_views[0]->cursor_visible();
106   EnableMenuItem(menu, ID_TOGGLE_BREAKPOINT, MF_BYCOMMAND | (disasm_cursor_visible ? MF_ENABLED : MF_GRAYED));
107   EnableMenuItem(menu, ID_RUN_TO_CURSOR, MF_BYCOMMAND | (disasm_cursor_visible ? MF_ENABLED : MF_GRAYED));
108
109   disasm_right_column const rightcol = downcast<disasmview_info *>(m_views[0].get())->right_column();
110   CheckMenuItem(menu, ID_SHOW_RAW, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_RAW ? MF_CHECKED : MF_UNCHECKED));
111   CheckMenuItem(menu, ID_SHOW_ENCRYPTED, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_ENCRYPTED ? MF_CHECKED : MF_UNCHECKED));
112   CheckMenuItem(menu, ID_SHOW_COMMENTS, MF_BYCOMMAND | (rightcol == DASM_RIGHTCOL_COMMENTS ? MF_CHECKED : MF_UNCHECKED));
113}
114
115
116bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam)
117{
118   disasmview_info *const dasmview = downcast<disasmview_info *>(m_views[0].get());
119
120   switch (HIWORD(wparam))
121   {
122   // menu selections
123   case 0:
124      switch (LOWORD(wparam))
125      {
126      case ID_SHOW_RAW:
127         dasmview->set_right_column(DASM_RIGHTCOL_RAW);
128         recompute_children();
129         return true;
130
131      case ID_SHOW_ENCRYPTED:
132         dasmview->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
133         recompute_children();
134         return true;
135
136      case ID_SHOW_COMMENTS:
137         dasmview->set_right_column(DASM_RIGHTCOL_COMMENTS);
138         recompute_children();
139         return true;
140
141      case ID_RUN_TO_CURSOR:
142         if (dasmview->cursor_visible())
143         {
144            offs_t const address = dasmview->selected_address();
145            if (dasmview->source_is_visible_cpu())
146            {
147               astring command;
148               command.printf("go 0x%X", address);
149               debug_console_execute_command(machine(), command, 1);
150            }
151            else
152            {
153               dasmview->source_device()->debug()->go(address);
154            }
155         }
156         return true;
157
158      case ID_TOGGLE_BREAKPOINT:
159         if (dasmview->cursor_visible())
160         {
161            offs_t const address = dasmview->selected_address();
162            device_debug *const debug = dasmview->source_device()->debug();
163            INT32 bpindex = -1;
164
165            /* first find an existing breakpoint at this address */
166            for (device_debug::breakpoint *bp = debug->breakpoint_first(); bp != NULL; bp = bp->next())
167            {
168               if (address == bp->address())
169               {
170                  bpindex = bp->index();
171                  break;
172               }
173            }
174
175            /* if it doesn't exist, add a new one */
176            if (dasmview->source_is_visible_cpu())
177            {
178               astring command;
179               if (bpindex == -1)
180                  command.printf("bpset 0x%X", address);
181               else
182                  command.printf("bpclear 0x%X", bpindex);
183               debug_console_execute_command(machine(), command, 1);
184            }
185            else
186            {
187               if (bpindex == -1)
188               {
189                  bpindex = debug->breakpoint_set(address, NULL, NULL);
190                  debug_console_printf(machine(), "Breakpoint %X set\n", bpindex);
191               }
192               else
193               {
194                  debug->breakpoint_clear(bpindex);
195                  debug_console_printf(machine(), "Breakpoint %X cleared\n", bpindex);
196               }
197               machine().debug_view().update_all();
198               debugger_refresh_display(machine());
199            }
200         }
201         return true;
202      }
203      break;
204   }
205   return editwin_info::handle_command(wparam, lparam);
206}
trunk/src/osd/modules/debugger/win/disasmbasewininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   disasmbasewininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__
10#define __DEBUG_WIN_DISASM_BASE_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "editwininfo.h"
15
16
17class disasmbasewin_info : public editwin_info
18{
19public:
20   disasmbasewin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler);
21   virtual ~disasmbasewin_info();
22
23   virtual bool handle_key(WPARAM wparam, LPARAM lparam);
24
25protected:
26   virtual void update_menu();
27   virtual bool handle_command(WPARAM wparam, LPARAM lparam);
28};
29
30#endif
trunk/src/osd/modules/debugger/win/disasmviewinfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   disasmviewinfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "disasmviewinfo.h"
10
11
12disasmview_info::disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
13   debugview_info(debugger, owner, parent, DVT_DISASSEMBLY)
14{
15}
16
17
18disasmview_info::~disasmview_info()
19{
20}
21
22
23disasm_right_column disasmview_info::right_column() const
24{
25   return view<debug_view_disasm>()->right_column();
26}
27
28
29offs_t disasmview_info::selected_address() const
30{
31   return view<debug_view_disasm>()->selected_address();
32}
33
34
35void disasmview_info::set_expression(char const *string)
36{
37   view<debug_view_disasm>()->set_expression(string);
38}
39
40
41void disasmview_info::set_right_column(disasm_right_column contents)
42{
43   view<debug_view_disasm>()->set_right_column(contents);
44}
No newline at end of file
trunk/src/osd/modules/debugger/win/disasmviewinfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   disasmviewinfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DISASM_VIEW_INFO_H__
10#define __DEBUG_WIN_DISASM_VIEW_INFO_H__
11
12#include "debugwin.h"
13
14#include "debugviewinfo.h"
15
16#include "debug/dvdisasm.h"
17
18
19class disasmview_info : public debugview_info
20{
21public:
22   disasmview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent);
23   virtual ~disasmview_info();
24
25   disasm_right_column right_column() const;
26   offs_t selected_address() const;
27
28   void set_expression(const char *expression);
29   void set_right_column(disasm_right_column contents);
30};
31
32#endif
trunk/src/osd/modules/debugger/win/disasmwininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   disasmwininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "disasmwininfo.h"
10
11#include "debugviewinfo.h"
12#include "disasmviewinfo.h"
13#include "uimetrics.h"
14
15#include "debugger.h"
16#include "debug/debugcon.h"
17#include "debug/debugcpu.h"
18
19#include "winutf8.h"
20
21
22disasmwin_info::disasmwin_info(debugger_windows_interface &debugger) :
23   disasmbasewin_info(debugger, false, "Disassembly", NULL),
24   m_combownd(NULL)
25{
26   if ((window() == NULL) || (m_views[0] == NULL))
27      return;
28
29   // set up the view to track the initial expression
30   set_edit_defstr("curpc");
31   set_editwnd_text("curpc");
32   editwnd_select_all();
33
34   // create a combo box
35   m_combownd = m_views[0]->create_source_combobox(window(), (LONG_PTR)this);
36
37   // set the caption
38   update_caption();
39
40   // recompute the children once to get the maxwidth
41   recompute_children();
42
43   // position the window and recompute children again
44   SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
45   recompute_children();
46
47   // mark the edit box as the default focus and set it
48   set_default_focus();
49}
50
51
52disasmwin_info::~disasmwin_info()
53{
54}
55
56
57void disasmwin_info::recompute_children()
58{
59   // compute a client rect
60   RECT bounds;
61   bounds.top = bounds.left = 0;
62   bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
63   bounds.bottom = 200;
64   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
65
66   // clamp the min/max size
67   set_maxwidth(bounds.right - bounds.left);
68
69   // get the parent's dimensions
70   RECT parent;
71   GetClientRect(window(), &parent);
72
73   // edit box gets half of the width
74   RECT editrect;
75   editrect.top = parent.top + EDGE_WIDTH;
76   editrect.bottom = editrect.top + metrics().debug_font_height() + 4;
77   editrect.left = parent.left + EDGE_WIDTH;
78   editrect.right = parent.left + ((parent.right - parent.left) / 2) - EDGE_WIDTH;
79
80   // combo box gets the other half of the width
81   RECT comborect;
82   comborect.top = editrect.top;
83   comborect.bottom = editrect.bottom;
84   comborect.left = editrect.right + (2 * EDGE_WIDTH);
85   comborect.right = parent.right - EDGE_WIDTH;
86
87   // disasm view gets the rest
88   RECT dasmrect;
89   dasmrect.top = editrect.bottom + (2 * EDGE_WIDTH);
90   dasmrect.bottom = parent.bottom - EDGE_WIDTH;
91   dasmrect.left = parent.left + EDGE_WIDTH;
92   dasmrect.right = parent.right - EDGE_WIDTH;
93
94   // set the bounds of things
95   m_views[0]->set_bounds(dasmrect);
96   set_editwnd_bounds(editrect);
97   smart_set_window_bounds(m_combownd, window(), comborect);
98}
99
100
101bool disasmwin_info::handle_command(WPARAM wparam, LPARAM lparam)
102{
103   switch (HIWORD(wparam))
104   {
105   // combo box selection changed
106   case CBN_SELCHANGE:
107      {
108         int const sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
109         if (sel != CB_ERR)
110         {
111            m_views[0]->set_source_index(sel);
112            update_caption();
113
114            // reset the focus
115            set_default_focus();
116            return true;
117         }
118         break;
119      }
120   }
121   return disasmbasewin_info::handle_command(wparam, lparam);
122}
123
124
125void disasmwin_info::draw_contents(HDC dc)
126{
127   disasmbasewin_info::draw_contents(dc);
128   if (m_combownd)
129      draw_border(dc, m_combownd);
130}
131
132
133void disasmwin_info::process_string(char const *string)
134{
135   // set the string to the disasm view
136   downcast<disasmview_info *>(m_views[0].get())->set_expression(string);
137
138   // select everything in the edit text box
139   editwnd_select_all();
140
141   // update the default string to match
142   set_edit_defstr(string);
143}
144
145
146void disasmwin_info::update_caption()
147{
148   win_set_window_text_utf8(window(), astring("Disassembly: ", m_views[0]->source_name()));
149}
trunk/src/osd/modules/debugger/win/disasmwininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   disasmwininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_DISASM_WIN_INFO_H__
10#define __DEBUG_WIN_DISASM_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "disasmbasewininfo.h"
15
16
17class disasmwin_info : public disasmbasewin_info
18{
19public:
20   disasmwin_info(debugger_windows_interface &debugger);
21   virtual ~disasmwin_info();
22
23protected:
24   virtual void recompute_children();
25   virtual bool handle_command(WPARAM wparam, LPARAM lparam);
26   virtual void draw_contents(HDC dc);
27
28private:
29   virtual void process_string(char const *string);
30
31   void update_caption();
32
33   HWND   m_combownd;
34};
35
36#endif
trunk/src/osd/modules/debugger/win/editwininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   editwininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "editwininfo.h"
10
11#include "debugviewinfo.h"
12#include "uimetrics.h"
13
14#include "strconv.h"
15
16
17// edit box styles
18#define   EDIT_BOX_STYLE      WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
19#define   EDIT_BOX_STYLE_EX   0
20
21
22editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
23   debugwin_info(debugger, is_main_console, title, handler),
24   m_editwnd(NULL),
25   m_edit_defstr(),
26   m_original_editproc(NULL),
27   m_history_count(0),
28   m_last_history(0)
29{
30   if (window() == NULL)
31      return;
32
33   // create an edit box and override its key handling
34   m_editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), NULL, EDIT_BOX_STYLE,
35         0, 0, 100, 100, window(), NULL, GetModuleHandle(NULL), NULL);
36   m_original_editproc = (WNDPROC)(FPTR)GetWindowLongPtr(m_editwnd, GWLP_WNDPROC);
37   SetWindowLongPtr(m_editwnd, GWLP_USERDATA, (LONG_PTR)this);
38   SetWindowLongPtr(m_editwnd, GWLP_WNDPROC, (LONG_PTR)&editwin_info::static_edit_proc);
39   SendMessage(m_editwnd, WM_SETFONT, (WPARAM)metrics().debug_font(), (LPARAM)FALSE);
40   SendMessage(m_editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
41   set_editwnd_text("");
42}
43
44
45editwin_info::~editwin_info()
46{
47}
48
49
50bool editwin_info::restore_field(HWND wnd)
51{
52   if (wnd == m_editwnd)
53   {
54      set_editwnd_text(m_edit_defstr);
55      editwnd_select_all();
56      return true;
57   }
58   else
59   {
60      return false;
61   }
62}
63
64
65bool editwin_info::set_default_focus()
66{
67   SetFocus(m_editwnd);
68   return true;
69}
70
71
72void editwin_info::set_editwnd_bounds(RECT const &bounds)
73{
74   smart_set_window_bounds(m_editwnd, window(), bounds);
75}
76
77
78void editwin_info::set_editwnd_text(char const *text)
79{
80   TCHAR *tc_buffer = tstring_from_utf8(text);
81   if (tc_buffer != NULL)
82   {
83      SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)tc_buffer);
84      osd_free(tc_buffer);
85   }
86}
87
88
89void editwin_info::editwnd_select_all()
90{
91   SendMessage(m_editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
92}
93
94
95void editwin_info::draw_contents(HDC dc)
96{
97   debugwin_info::draw_contents(dc);
98   if (m_editwnd)
99      draw_border(dc, m_editwnd);
100}
101
102
103LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
104{
105   TCHAR buffer[MAX_EDIT_STRING];
106
107   // handle a few messages
108   switch (message)
109   {
110   // key down: handle navigation in the attached view
111   case WM_SYSKEYDOWN:
112      if (wparam != VK_F10)
113         return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
114      // (fall through)
115   case WM_KEYDOWN:
116      switch (wparam)
117      {
118      case VK_UP:
119         if (m_last_history < (m_history_count - 1))
120            m_last_history++;
121         else
122            m_last_history = 0;
123         SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
124         SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
125         break;
126
127      case VK_DOWN:
128         if (m_last_history > 0)
129            m_last_history--;
130         else if (m_history_count > 0)
131            m_last_history = m_history_count - 1;
132         else
133            m_last_history = 0;
134         SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
135         SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
136         break;
137
138      case VK_PRIOR:
139         if (m_views[0] != NULL)
140            m_views[0]->send_pageup();
141         break;
142
143      case VK_NEXT:
144         if (m_views[0] != NULL)
145            m_views[0]->send_pagedown();
146         break;
147
148      case VK_TAB:
149         if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
150            prev_view(NULL);
151         else
152            next_view(NULL);
153         set_ignore_char_lparam(lparam);
154         break;
155
156      default:
157         if (handle_key(wparam, lparam))
158            set_ignore_char_lparam(lparam);
159         else
160            return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
161         break;
162      }
163      break;
164
165   // char: handle the return key
166   case WM_CHAR:
167
168      // ignore chars associated with keys we've handled
169      if (check_ignore_char_lparam(lparam))
170      {
171         if (waiting_for_debugger() || !seq_pressed())
172         {
173            switch (wparam)
174            {
175            case 13:
176               {
177                  // fetch the text
178                  SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)ARRAY_LENGTH(buffer), (LPARAM)buffer);
179
180                  // add to the history if it's not a repeat of the last one
181                  if (buffer[0] != 0 && _tcscmp(buffer, &m_history[0][0]))
182                  {
183                     memmove(&m_history[1][0], &m_history[0][0], (HISTORY_LENGTH - 1) * MAX_EDIT_STRING * sizeof(TCHAR));
184                     _tcscpy(&m_history[0][0], buffer);
185                     if (m_history_count < HISTORY_LENGTH)
186                        m_history_count++;
187                  }
188                  m_last_history = m_history_count - 1;
189
190                  // process
191                  char *utf8_buffer = utf8_from_tstring(buffer);
192                  if (utf8_buffer != NULL)
193                  {
194                     process_string(utf8_buffer);
195                     osd_free(utf8_buffer);
196                  }
197                  break;
198               }
199
200            case 27:
201               {
202                  // fetch the text
203                  SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer);
204
205                  // if it's not empty, clear the text
206                  if (_tcslen(buffer) > 0)
207                  {
208                     set_ignore_char_lparam(lparam);
209                     set_editwnd_text(m_edit_defstr);
210                     editwnd_select_all();
211                  }
212                  break;
213               }
214
215            default:
216               return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
217            }
218         }
219      }
220      break;
221
222   // everything else: defaults
223   default:
224      return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
225   }
226
227   return 0;
228}
229
230
231LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
232{
233   editwin_info *const info = (editwin_info *)(FPTR)GetWindowLongPtr(wnd, GWLP_USERDATA);
234   assert(info.m_editwnd == wnd);
235   return info->edit_proc(message, wparam, lparam);
236}
trunk/src/osd/modules/debugger/win/editwininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   editwininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_EDIT_WIN_INFO_H__
10#define __DEBUG_WIN_EDIT_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "debugwininfo.h"
15
16
17class editwin_info : public debugwin_info
18{
19public:
20   editwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler);
21   virtual ~editwin_info();
22
23   virtual bool restore_field(HWND wnd);
24
25   virtual bool set_default_focus();
26
27protected:
28   static DWORD const   COMBO_BOX_STYLE      = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
29   static DWORD const   COMBO_BOX_STYLE_EX   = 0;
30
31   void set_editwnd_bounds(RECT const &bounds);
32   void set_editwnd_text(char const *text);
33   void editwnd_select_all();
34   void set_edit_defstr(char const *string) { m_edit_defstr = string; }
35
36   virtual void draw_contents(HDC dc);
37
38private:
39   virtual void process_string(char const *string) = 0;
40
41   LRESULT edit_proc(UINT message, WPARAM wparam, LPARAM lparam);
42
43   static LRESULT CALLBACK static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
44
45   static int const   MAX_EDIT_STRING = 256;
46   static int const   HISTORY_LENGTH = 20;
47
48   HWND            m_editwnd;
49   astring            m_edit_defstr;
50   WNDPROC            m_original_editproc;
51   TCHAR            m_history[HISTORY_LENGTH][MAX_EDIT_STRING];
52   int               m_history_count;
53   int               m_last_history;
54};
55
56#endif
trunk/src/osd/modules/debugger/win/logwininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   logwininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "logwininfo.h"
10
11#include "debugviewinfo.h"
12
13
14logwin_info::logwin_info(debugger_windows_interface &debugger) :
15   debugwin_info(debugger, false, astring("Errorlog: ", debugger.machine().system().description, " [", debugger.machine().system().name, "]"), NULL)
16{
17   if (!window())
18      return;
19
20   m_views[0].reset(global_alloc(debugview_info(debugger, *this, window(), DVT_LOG)));
21   if ((m_views[0] == NULL) || !m_views[0]->is_valid())
22   {
23      m_views[0].reset();
24      return;
25   }
26
27   // compute a client rect
28   RECT bounds;
29   bounds.top = bounds.left = 0;
30   bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
31   bounds.bottom = 200;
32   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
33
34   // clamp the min/max size
35   set_maxwidth(bounds.right - bounds.left);
36
37   // position the window at the bottom-right
38   SetWindowPos(window(), HWND_TOP, 100, 100, bounds.right - bounds.left, bounds.bottom - bounds.top, SWP_SHOWWINDOW);
39
40   // recompute the children
41   recompute_children();
42}
43
44
45logwin_info::~logwin_info()
46{
47}
48
49
50void logwin_info::recompute_children()
51{
52   // compute a client rect
53   RECT bounds;
54   bounds.top = bounds.left = 0;
55   bounds.right = m_views[0]->maxwidth() + (2 * EDGE_WIDTH);
56   bounds.bottom = 200;
57   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
58
59   // clamp the min/max size
60   set_maxwidth(bounds.right - bounds.left);
61
62   // get the parent's dimensions
63   RECT parent;
64   GetClientRect(window(), &parent);
65
66   // view gets the remaining space
67   InflateRect(&parent, -EDGE_WIDTH, -EDGE_WIDTH);
68   m_views[0]->set_bounds(parent);
69}
trunk/src/osd/modules/debugger/win/logwininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   logwininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_LOG_WIN_INFO_H__
10#define __DEBUG_WIN_LOG_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "debugwininfo.h"
15
16
17class logwin_info : public debugwin_info
18{
19public:
20   logwin_info(debugger_windows_interface &debugger);
21   virtual ~logwin_info();
22
23private:
24   virtual void recompute_children();
25};
26
27#endif
trunk/src/osd/modules/debugger/win/memoryviewinfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   memoryviewinfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "memoryviewinfo.h"
10
11#include "debug/dvmemory.h"
12
13
14memoryview_info::memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent) :
15   debugview_info(debugger, owner, parent, DVT_MEMORY)
16{
17}
18
19
20memoryview_info::~memoryview_info()
21{
22}
23
24
25UINT8 memoryview_info::bytes_per_chunk() const
26{
27   return view<debug_view_memory>()->bytes_per_chunk();
28}
29
30
31UINT32 memoryview_info::chunks_per_row() const
32{
33   return view<debug_view_memory>()->chunks_per_row();
34}
35
36
37bool memoryview_info::reverse() const
38{
39   return view<debug_view_memory>()->reverse();
40}
41
42
43bool memoryview_info::physical() const
44{
45   return view<debug_view_memory>()->physical();
46}
47
48
49void memoryview_info::set_expression(char const *string)
50{
51   view<debug_view_memory>()->set_expression(string);
52}
53
54void memoryview_info::set_bytes_per_chunk(UINT8 chunkbytes)
55{
56   view<debug_view_memory>()->set_bytes_per_chunk(chunkbytes);
57}
58
59void memoryview_info::set_chunks_per_row(UINT32 rowchunks)
60{
61   view<debug_view_memory>()->set_chunks_per_row(rowchunks);
62}
63
64void memoryview_info::set_reverse(bool reverse)
65{
66   view<debug_view_memory>()->set_reverse(reverse);
67}
68
69void memoryview_info::set_physical(bool physical)
70{
71   view<debug_view_memory>()->set_physical(physical);
72}
trunk/src/osd/modules/debugger/win/memoryviewinfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   memoryviewinfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_MEMORY_VIEW_INFO_H__
10#define __DEBUG_WIN_MEMORY_VIEW_INFO_H__
11
12#include "debugwin.h"
13
14#include "debugviewinfo.h"
15
16
17class memoryview_info : public debugview_info
18{
19public:
20   memoryview_info(debugger_windows_interface &debugger, debugwin_info &owner, HWND parent);
21   virtual ~memoryview_info();
22
23   UINT8 bytes_per_chunk() const;
24   UINT32 chunks_per_row() const;
25   bool reverse() const;
26   bool ascii() const;
27   bool physical() const;
28
29   void set_expression(char const *string);
30   void set_bytes_per_chunk(UINT8 chunkbytes);
31   void set_chunks_per_row(UINT32 rowchunks);
32   void set_reverse(bool reverse);
33   void set_physical(bool physical);
34};
35
36#endif
trunk/src/osd/modules/debugger/win/memorywininfo.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   memorywininfo.c - Win32 debug window handling
6//
7//============================================================
8
9#include "memorywininfo.h"
10
11#include "debugviewinfo.h"
12#include "memoryviewinfo.h"
13#include "uimetrics.h"
14
15#include "winutf8.h"
16
17
18memorywin_info::memorywin_info(debugger_windows_interface &debugger) :
19   editwin_info(debugger, false, "Memory", NULL),
20   m_combownd(NULL)
21{
22   if (!window())
23      return;
24
25   m_views[0].reset(global_alloc(memoryview_info(debugger, *this, window())));
26   if ((m_views[0] == NULL) || !m_views[0]->is_valid())
27   {
28      m_views[0].reset();
29      return;
30   }
31
32   // create the options menu
33   HMENU const optionsmenu = CreatePopupMenu();
34   AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS, TEXT("1-byte chunks\tCtrl+1"));
35   AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS, TEXT("2-byte chunks\tCtrl+2"));
36   AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS, TEXT("4-byte chunks\tCtrl+4"));
37   AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS, TEXT("8-byte chunks\tCtrl+8"));
38   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
39   AppendMenu(optionsmenu, MF_ENABLED, ID_LOGICAL_ADDRESSES, TEXT("Logical Addresses\tCtrl+L"));
40   AppendMenu(optionsmenu, MF_ENABLED, ID_PHYSICAL_ADDRESSES, TEXT("Physical Addresses\tCtrl+Y"));
41   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
42   AppendMenu(optionsmenu, MF_ENABLED, ID_REVERSE_VIEW, TEXT("Reverse View\tCtrl+R"));
43   AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
44   AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase bytes per line\tCtrl+P"));
45   AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease bytes per line\tCtrl+O"));
46   AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
47
48   // set up the view to track the initial expression
49   downcast<memoryview_info *>(m_views[0].get())->set_expression("0");
50   set_edit_defstr("0");
51   set_editwnd_text("0");
52   editwnd_select_all();
53
54   // create a combo box
55   m_views[0]->set_source_for_visible_cpu();
56   m_combownd = m_views[0]->create_source_combobox(window(), (LONG_PTR)this);
57
58   // set the caption
59   update_caption();
60
61   // recompute the children once to get the maxwidth
62   recompute_children();
63
64   // position the window and recompute children again
65   SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
66   recompute_children();
67
68   // mark the edit box as the default focus and set it
69   set_default_focus();
70}
71
72
73memorywin_info::~memorywin_info()
74{
75}
76
77
78bool memorywin_info::handle_key(WPARAM wparam, LPARAM lparam)
79{
80   if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
81   {
82      switch (wparam)
83      {
84      case '1':
85         SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS, 0);
86         return true;
87
88      case '2':
89         SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS, 0);
90         return true;
91
92      case '4':
93         SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS, 0);
94         return true;
95
96      case '8':
97         SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS, 0);
98         return true;
99
100      case 'L':
101         SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0);
102         return true;
103
104      case 'Y':
105         SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0);
106         return true;
107
108      case 'R':
109         SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0);
110         return true;
111
112      case 'P':
113         SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0);
114         return true;
115
116      case 'O':
117         SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0);
118         return true;
119      }
120   }
121   return editwin_info::handle_key(wparam, lparam);
122}
123
124
125void memorywin_info::recompute_children()
126{
127   // compute a client rect
128   RECT bounds;
129   bounds.top = bounds.left = 0;
130   bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
131   bounds.bottom = 200;
132   AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
133
134   // clamp the min/max size
135   set_maxwidth(bounds.right - bounds.left);
136
137   // get the parent's dimensions
138   RECT parent;
139   GetClientRect(window(), &parent);
140
141   // edit box gets half of the width
142   RECT editrect;
143   editrect.top = parent.top + EDGE_WIDTH;
144   editrect.bottom = editrect.top + metrics().debug_font_height() + 4;
145   editrect.left = parent.left + EDGE_WIDTH;
146   editrect.right = parent.left + ((parent.right - parent.left) / 2) - EDGE_WIDTH;
147
148   // combo box gets the other half of the width
149   RECT comborect;
150   comborect.top = editrect.top;
151   comborect.bottom = editrect.bottom;
152   comborect.left = editrect.right + (2 * EDGE_WIDTH);
153   comborect.right = parent.right - EDGE_WIDTH;
154
155   // memory view gets the rest
156   RECT memrect;
157   memrect.top = editrect.bottom + (2 * EDGE_WIDTH);
158   memrect.bottom = parent.bottom - EDGE_WIDTH;
159   memrect.left = parent.left + EDGE_WIDTH;
160   memrect.right = parent.right - EDGE_WIDTH;
161
162   // set the bounds of things
163   m_views[0]->set_bounds(memrect);
164   set_editwnd_bounds(editrect);
165   smart_set_window_bounds(m_combownd, window(), comborect);
166}
167
168
169void memorywin_info::update_menu()
170{
171   editwin_info::update_menu();
172
173   memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get());
174   HMENU const menu = GetMenu(window());
175   CheckMenuItem(menu, ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 1 ? MF_CHECKED : MF_UNCHECKED));
176   CheckMenuItem(menu, ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 2 ? MF_CHECKED : MF_UNCHECKED));
177   CheckMenuItem(menu, ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 4 ? MF_CHECKED : MF_UNCHECKED));
178   CheckMenuItem(menu, ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->bytes_per_chunk() == 8 ? MF_CHECKED : MF_UNCHECKED));
179   CheckMenuItem(menu, ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED));
180   CheckMenuItem(menu, ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED));
181   CheckMenuItem(menu, ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED));
182   EnableMenuItem(menu, ID_DECREASE_MEM_WIDTH, MF_BYCOMMAND | ((memview->chunks_per_row() > 1) ? MF_ENABLED : MF_GRAYED));
183}
184
185
186bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam)
187{
188   memoryview_info *const memview = downcast<memoryview_info *>(m_views[0].get());
189   switch (HIWORD(wparam))
190   {
191   // combo box selection changed
192   case CBN_SELCHANGE:
193      {
194         int const sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
195         if (sel != CB_ERR)
196         {
197            memview->set_source_index(sel);
198            update_caption();
199
200            // reset the focus
201            set_default_focus();
202            return true;
203         }
204         break;
205      }
206
207   // menu selections
208   case 0:
209      switch (LOWORD(wparam))
210      {
211      case ID_1_BYTE_CHUNKS:
212         memview->set_bytes_per_chunk(1);
213         return true;
214
215      case ID_2_BYTE_CHUNKS:
216         memview->set_bytes_per_chunk(2);
217         return true;
218
219      case ID_4_BYTE_CHUNKS:
220         memview->set_bytes_per_chunk(4);
221         return true;
222
223      case ID_8_BYTE_CHUNKS:
224         memview->set_bytes_per_chunk(8);
225         return true;
226
227      case ID_LOGICAL_ADDRESSES:
228         memview->set_physical(false);
229         return true;
230
231      case ID_PHYSICAL_ADDRESSES:
232         memview->set_physical(true);
233         return true;
234
235      case ID_REVERSE_VIEW:
236         memview->set_reverse(!memview->reverse());
237         return true;
238
239      case ID_INCREASE_MEM_WIDTH:
240         memview->set_chunks_per_row(memview->chunks_per_row() + 1);
241         recompute_children();
242         return true;
243
244      case ID_DECREASE_MEM_WIDTH:
245         memview->set_chunks_per_row(memview->chunks_per_row() - 1);
246         recompute_children();
247         return true;
248      }
249      break;
250   }
251   return editwin_info::handle_command(wparam, lparam);
252}
253
254
255void memorywin_info::draw_contents(HDC dc)
256{
257   editwin_info::draw_contents(dc);
258   if (m_combownd)
259      draw_border(dc, m_combownd);
260}
261
262
263void memorywin_info::process_string(char const *string)
264{
265   // set the string to the memory view
266   downcast<memoryview_info *>(m_views[0].get())->set_expression(string);
267
268   // select everything in the edit text box
269   editwnd_select_all();
270
271   // update the default string to match
272   set_edit_defstr(string);
273}
274
275
276void memorywin_info::update_caption()
277{
278   win_set_window_text_utf8(window(), astring("Memory: ", m_views[0]->source_name()));
279}
trunk/src/osd/modules/debugger/win/memorywininfo.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   memorywininfo.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_MEMORY_WIN_INFO_H__
10#define __DEBUG_WIN_MEMORY_WIN_INFO_H__
11
12#include "debugwin.h"
13
14#include "editwininfo.h"
15
16
17class memorywin_info : public editwin_info
18{
19public:
20   memorywin_info(debugger_windows_interface &debugger);
21   virtual ~memorywin_info();
22
23   virtual bool handle_key(WPARAM wparam, LPARAM lparam);
24
25protected:
26   virtual void recompute_children();
27   virtual void update_menu();
28   virtual bool handle_command(WPARAM wparam, LPARAM lparam);
29   virtual void draw_contents(HDC dc);
30
31private:
32   virtual void process_string(char const *string);
33
34   void update_caption();
35
36   HWND   m_combownd;
37};
38
39#endif
trunk/src/osd/modules/debugger/win/uimetrics.c
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   uimetrics.c - Win32 debug window handling
6//
7//============================================================
8
9#include "uimetrics.h"
10
11#include "strconv.h"
12
13
14ui_metrics::ui_metrics(windows_options const &options) :
15   m_debug_font(NULL),
16   m_debug_font_height(0),
17   m_debug_font_width(0),
18   m_debug_font_ascent(0),
19   m_hscroll_height(GetSystemMetrics(SM_CYHSCROLL)),
20   m_vscroll_width(GetSystemMetrics(SM_CXVSCROLL))
21{
22   // create a temporary DC
23   HDC const temp_dc = GetDC(NULL);
24   if (temp_dc != NULL)
25   {
26      int const size = options.debugger_font_size();
27
28      // create a standard font
29      TCHAR *t_face = tstring_from_utf8(options.debugger_font());
30      m_debug_font = CreateFont(-MulDiv(size, GetDeviceCaps(temp_dc, LOGPIXELSY), 72), 0, 0, 0, FW_MEDIUM, FALSE, FALSE, FALSE,
31               ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, t_face);
32      osd_free(t_face);
33      t_face = NULL;
34
35      if (m_debug_font == NULL)
36         fatalerror("Unable to create debugger font\n");
37
38      // get the metrics
39      HGDIOBJ const old_font = SelectObject(temp_dc, m_debug_font);
40      TEXTMETRIC metrics;
41      if (GetTextMetrics(temp_dc, &metrics))
42      {
43         m_debug_font_width = metrics.tmAveCharWidth;
44         m_debug_font_height = metrics.tmHeight;
45         m_debug_font_ascent = metrics.tmAscent + metrics.tmExternalLeading;
46      }
47      SelectObject(temp_dc, old_font);
48      ReleaseDC(NULL, temp_dc);
49   }
50}
51
52
53ui_metrics::ui_metrics(ui_metrics const &that) :
54   m_debug_font(NULL),
55   m_debug_font_height(that.m_debug_font_height),
56   m_debug_font_width(that.m_debug_font_width),
57   m_debug_font_ascent(that.m_debug_font_ascent),
58   m_hscroll_height(that.m_hscroll_height),
59   m_vscroll_width(that.m_vscroll_width)
60{
61   LOGFONT lf;
62   if (GetObject(that.m_debug_font, sizeof(lf), &lf))
63      m_debug_font = CreateFontIndirect(&lf);
64}
65
66
67ui_metrics::~ui_metrics()
68{
69   if (m_debug_font)
70      DeleteObject(m_debug_font);
71}
trunk/src/osd/modules/debugger/win/uimetrics.h
r0r243671
1// license:BSD-3-Clause
2// copyright-holders:Aaron Giles, Vas Crabb
3//============================================================
4//
5//   uimetrics.h - Win32 debug window handling
6//
7//============================================================
8
9#ifndef __DEBUG_WIN_UI_METRICS_H__
10#define __DEBUG_WIN_UI_METRICS_H__
11
12#include "debugwin.h"
13
14#include "emu.h"
15
16#include "winmain.h"
17
18
19class ui_metrics
20{
21public:
22   ui_metrics(windows_options const &options);
23   ui_metrics(ui_metrics const &that);
24   ~ui_metrics();
25
26   HFONT debug_font() const { return m_debug_font; }
27   UINT32 debug_font_height() const { return m_debug_font_height; }
28   UINT32 debug_font_width() const { return m_debug_font_width; }
29   UINT32 debug_font_ascent() const { return m_debug_font_ascent; }
30
31   UINT32 hscroll_height() const { return m_hscroll_height; }
32   UINT32 vscroll_width() const { return m_vscroll_width; }
33
34private:
35   HFONT m_debug_font;
36   UINT32 m_debug_font_height;
37   UINT32 m_debug_font_width;
38   UINT32 m_debug_font_ascent;
39
40   UINT32 const m_hscroll_height;
41   UINT32 const m_vscroll_width;
42};
43
44#endif
trunk/src/osd/sdl/sdl.mak
r243670r243671
767767   $(OSDOBJ)/modules/debugger/none.o \
768768   $(OSDOBJ)/modules/debugger/debugint.o \
769769   $(OSDOBJ)/modules/debugger/debugwin.o \
770   $(OSDOBJ)/modules/debugger/debugqt.o \
770   $(OSDOBJ)/modules/debugger/debugqt.o
771771
772772#-------------------------------------------------
773773# BGFX
trunk/src/osd/windows/windows.mak
r243670r243671
9393   $(OSDOBJ)/modules/midi \
9494   $(OSDOBJ)/modules/font \
9595   $(OSDOBJ)/modules/netdev \
96   $(OSDOBJ)/modules/debugger/win
9697
9798ifdef USE_QTDEBUG
9899OBJDIRS += $(OSDOBJ)/modules/debugger/qt
r243670r243671
411412# add debug-specific files
412413OSDOBJS += \
413414   $(OSDOBJ)/modules/debugger/debugwin.o \
415   $(OSDOBJ)/modules/debugger/win/consolewininfo.o \
416   $(OSDOBJ)/modules/debugger/win/debugbaseinfo.o \
417   $(OSDOBJ)/modules/debugger/win/debugviewinfo.o \
418   $(OSDOBJ)/modules/debugger/win/debugwininfo.o \
419   $(OSDOBJ)/modules/debugger/win/disasmbasewininfo.o \
420   $(OSDOBJ)/modules/debugger/win/disasmviewinfo.o \
421   $(OSDOBJ)/modules/debugger/win/disasmwininfo.o \
422   $(OSDOBJ)/modules/debugger/win/editwininfo.o \
423   $(OSDOBJ)/modules/debugger/win/logwininfo.o \
424   $(OSDOBJ)/modules/debugger/win/memoryviewinfo.o \
425   $(OSDOBJ)/modules/debugger/win/memorywininfo.o \
426   $(OSDOBJ)/modules/debugger/win/uimetrics.o \
414427   $(OSDOBJ)/modules/debugger/debugint.o \
415428   $(OSDOBJ)/modules/debugger/debugqt.o \
416   $(OSDOBJ)/modules/debugger/none.o \
429   $(OSDOBJ)/modules/debugger/none.o
417430
418431# add a stub resource file
419432RESFILE = $(WINOBJ)/mame.res
trunk/src/osd/windows/winmain.h
r243670r243671
66//
77//============================================================
88
9#ifndef __WINDOWS_WINMAIN_H__
10#define __WINDOWS_WINMAIN_H__
11
912#include "clifront.h"
1013#include "osdepend.h"
1114#include "modules/lib/osdobj_common.h"
r243670r243671
292295// use this to ping the watchdog
293296void winmain_watchdog_ping(void);
294297void winmain_dump_stack();
298
299#endif
No newline at end of file


Previous 199869 Revisions Next


© 1997-2024 The MAME Team