diff options
Diffstat (limited to 'gdb/mac-xdep.c')
-rw-r--r-- | gdb/mac-xdep.c | 1087 |
1 files changed, 1087 insertions, 0 deletions
diff --git a/gdb/mac-xdep.c b/gdb/mac-xdep.c new file mode 100644 index 00000000000..bf3f78deb1f --- /dev/null +++ b/gdb/mac-xdep.c @@ -0,0 +1,1087 @@ +/* Top level support for Mac interface to GDB, the GNU debugger. + Copyright 1994 Free Software Foundation, Inc. + Contributed by Cygnus Support. Written by Stan Shebs. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "defs.h" + +#include <readline/readline.h> +#include <readline/history.h> + +#include <Types.h> +#include <Resources.h> +#include <QuickDraw.h> +#include <Fonts.h> +#include <Events.h> +#include <Windows.h> +#include <Menus.h> +#include <TextEdit.h> +#include <Dialogs.h> +#include <Desk.h> +#include <ToolUtils.h> +#include <Memory.h> +#include <SegLoad.h> +#include <Files.h> +#include <Folders.h> +#include <OSUtils.h> +#include <OSEvents.h> +#include <DiskInit.h> +#include <Packages.h> +#include <Traps.h> +#include <Lists.h> +#include <Gestalt.h> +#include <PPCToolbox.h> +#include <AppleEvents.h> +#include <StandardFile.h> +#include <Sound.h> + +#ifdef MPW +#define QD(whatever) (qd.##whatever) +#define QDPat(whatever) (&(qd.##whatever)) +#endif /* MPW */ + +#ifdef THINK_C +#define QD(whatever) (whatever) +#endif + +#define p2c(pstr,cbuf) \ + strncpy(cbuf, ((char *) (pstr) + 1), pstr[0]); \ + cbuf[pstr[0]] = '\0'; + +#define pascalify(STR) \ + sprintf(tmpbuf, " %s", STR); \ + tmpbuf[0] = strlen(STR); + +#include "gdbcmd.h" +#include "call-cmds.h" +#include "symtab.h" +#include "inferior.h" +#include "signals.h" +#include "target.h" +#include "breakpoint.h" +#include "gdbtypes.h" +#include "expression.h" +#include "language.h" + +#include "mac-defs.h" + +int debug_openp = 0; + +/* This is true if we are running as a standalone application. */ + +int mac_app; + +/* This is true if we are using WaitNextEvent. */ + +int use_wne; + +/* This is true if we have Color Quickdraw. */ + +int has_color_qd; + +/* This is true if we are using Color Quickdraw. */ + +int use_color_qd; + +int inbackground; + +Rect dragrect = { -32000, -32000, 32000, 32000 }; +Rect sizerect; + +int sbarwid = 15; + +/* Globals for the console window. */ + +WindowPtr console_window; + +ControlHandle console_v_scrollbar; + +Rect console_v_scroll_rect; + +TEHandle console_text; + +Rect console_text_rect; + +/* This will go away eventually. */ +gdb_has_a_terminal () { return 1; } + +mac_init () +{ + SysEnvRec se; + int eventloopdone = 0; + char *str; + Boolean gotevent; + Point mouse; + EventRecord event; + WindowPtr win; + RgnHandle cursorRgn; + int i; + Handle menubar; + MenuHandle menu; + Handle siow_resource; + + mac_app = 0; + + str = getenv("DEBUG_GDB"); + if (str != NULL && str[0] != '\0') + { + if (strcmp(str, "openp") == 0) + debug_openp = 1; + } + + /* Don't do anything if we`re running under MPW. */ + if (!StandAlone) + return; + + /* Don't do anything if we're using SIOW. */ + /* This test requires that the siow 0 resource, as defined in + {RIncludes}siow.r, not be messed with. If it is, then the + standard Mac setup below will step on SIOW's Mac setup and + most likely crash the machine. */ + siow_resource = GetResource('siow', 0); + if (siow_resource != nil) + return; + + mac_app = 1; + + /* Do the standard Mac environment setup. */ + InitGraf (&QD (thePort)); + InitFonts (); + FlushEvents (everyEvent, 0); + InitWindows (); + InitMenus (); + TEInit (); + InitDialogs (NULL); + InitCursor (); + + /* Color Quickdraw is different from Classic QD. */ + SysEnvirons(2, &se); + has_color_qd = se.hasColorQD; + /* Use it if we got it. */ + use_color_qd = has_color_qd; + + sizerect.top = 50; + sizerect.left = 50; + sizerect.bottom = 1000; + sizerect.right = 1000; +#if 0 + sizerect.bottom = screenBits.bounds.bottom - screenBits.bounds.top; + sizerect.right = screenBits.bounds.right - screenBits.bounds.left; +#endif + + /* Set up the menus. */ + menubar = GetNewMBar (mbMain); + SetMenuBar (menubar); + /* Add the DAs etc as usual. */ + menu = GetMHandle (mApple); + if (menu != nil) { + AddResMenu (menu, 'DRVR'); + } + DrawMenuBar (); + + new_console_window (); +} + +new_console_window () +{ + /* Create the main window we're going to play in. */ + if (has_color_qd) + console_window = GetNewCWindow (wConsole, NULL, (WindowPtr) -1L); + else + console_window = GetNewWindow (wConsole, NULL, (WindowPtr) -1L); + + SetPort (console_window); + console_text_rect = console_window->portRect; + /* Leave 8 pixels of blank space, for aesthetic reasons and to + make it easier to select from the beginning of a line. */ + console_text_rect.left += 8; + console_text_rect.bottom -= sbarwid - 1; + console_text_rect.right -= sbarwid - 1; + console_text = TENew (&console_text_rect, &console_text_rect); + TESetSelect (0, 40000, console_text); + TEDelete (console_text); + TEAutoView (1, console_text); + + console_v_scroll_rect = console_window->portRect; + console_v_scroll_rect.bottom -= sbarwid - 1; + console_v_scroll_rect.left = console_v_scroll_rect.right - sbarwid; + console_v_scrollbar = + NewControl (console_window, &console_v_scroll_rect, + "\p", 1, 0, 0, 0, scrollBarProc, 0L); + + ShowWindow (console_window); + SelectWindow (console_window); +} + +mac_command_loop() +{ + SysEnvRec se; + int eventloopdone = 0; + Boolean gotevent; + Point mouse; + EventRecord event; + WindowPtr win; + RgnHandle cursorRgn; + int i, tm; + Handle menubar; + MenuHandle menu; + + /* Figure out if the WaitNextEvent Trap is available. */ + use_wne = + (NGetTrapAddress (0x60, ToolTrap) != NGetTrapAddress (0x9f, ToolTrap)); + /* Pass WaitNextEvent an empty region the first time through. */ + cursorRgn = NewRgn (); + /* Go into the main event-handling loop. */ + while (!eventloopdone) + { + /* Use WaitNextEvent if it is available, otherwise GetNextEvent. */ + if (use_wne) + { + get_global_mouse (&mouse); + adjust_cursor (mouse, cursorRgn); + tm = GetCaretTime(); + gotevent = WaitNextEvent (everyEvent, &event, tm, cursorRgn); + } + else + { + SystemTask (); + gotevent = GetNextEvent (everyEvent, &event); + } + /* First decide if the event is for a dialog or is just any old event. */ + if (FrontWindow () != nil && IsDialogEvent (&event)) + { + short itemhit; + DialogPtr dialog; + + /* Handle all the modeless dialogs here. */ + if (DialogSelect (&event, &dialog, &itemhit)) + { + } + } + else if (gotevent) + { + /* Make sure we have the right cursor before handling the event. */ + adjust_cursor (event.where, cursorRgn); + do_event (&event); + } + else + { + do_idle (); + } + } +} + +/* Collect the global coordinates of the mouse pointer. */ + +get_global_mouse (mouse) +Point *mouse; +{ + EventRecord evt; + + OSEventAvail (0, &evt); + *mouse = evt.where; +} + +/* Change the cursor's appearance to be appropriate for the given mouse + location. */ + +adjust_cursor (mouse, region) +Point mouse; +RgnHandle region; +{ +} + +/* Decipher an event, maybe do something with it. */ + +do_event (evt) +EventRecord *evt; +{ + short part, err, rslt = 0; + WindowPtr win; + Boolean hit; + char key; + Point pnt; + + switch (evt->what) + { + case mouseDown: + /* See if the click happened in a special part of the screen. */ + part = FindWindow (evt->where, &win); + switch (part) + { + case inMenuBar: + adjust_menus (); + do_menu_command (MenuSelect (evt->where)); + break; + case inSysWindow: + SystemClick (evt, win); + break; + case inContent: + if (win != FrontWindow ()) + { + /* Bring the clicked-on window to the front. */ + SelectWindow (win); + /* Fix the menu to match the new front window. */ + adjust_menus (); + /* We always want to discard the event now, since clicks in a + windows are often irreversible actions. */ + } else + /* Mouse clicks in the front window do something useful. */ + do_mouse_down (win, evt); + break; + case inDrag: + /* Standard drag behavior, no tricks necessary. */ + DragWindow (win, evt->where, &dragrect); + break; + case inGrow: + grow_window (win, evt->where); + break; + case inZoomIn: + case inZoomOut: + zoom_window (win, evt->where, part); + break; + case inGoAway: + close_window (win); + break; + } + break; + case keyDown: + case autoKey: + key = evt->message & charCodeMask; + /* Check for menukey equivalents. */ + if (evt->modifiers & cmdKey) + { + if (evt->what == keyDown) + { + adjust_menus (); + do_menu_command (MenuKey (key)); + } + } + else + { + if (evt->what == keyDown) + { + /* Random keypress, interpret it. */ + do_keyboard_command (key); + } + } + break; + case activateEvt: + activate_window ((WindowPtr) evt->message, evt->modifiers & activeFlag); + break; + case updateEvt: + update_window ((WindowPtr) evt->message); + break; + case diskEvt: + /* Call DIBadMount in response to a diskEvt, so that the user can format + a floppy. (from DTS Sample) */ + if (HiWord (evt->message) != noErr) + { + SetPt (&pnt, 50, 50); + err = DIBadMount (pnt, evt->message); + } + break; + case app4Evt: + /* Grab only a single byte. */ + switch ((evt->message >> 24) & 0xFF) + { + case 0xfa: + break; + case 1: + inbackground = !(evt->message & 1); + activate_window (FrontWindow (), !inbackground); + break; + } + break; + case kHighLevelEvent: + AEProcessAppleEvent (evt); + break; + case nullEvent: + do_idle (); + rslt = 1; + break; + default: + break; + } + return rslt; +} + +/* Do any idle-time activities. */ + +do_idle () +{ + TEIdle (console_text); +} + +grow_window (win, where) +WindowPtr win; +Point where; +{ + long winsize; + int h, v; + GrafPtr oldport; + + winsize = GrowWindow (win, where, &sizerect); + /* Only do anything if it actually changed size. */ + if (winsize != 0) + { + GetPort (&oldport); + SetPort (win); + if (win == console_window) + { + EraseRect (&win->portRect); + h = LoWord (winsize); + v = HiWord (winsize); + SizeWindow (win, h, v, 1); + resize_console_window (); + } + SetPort (oldport); + } +} + +zoom_window (win, where, part) +WindowPtr win; +Point where; +short part; +{ + ZoomWindow (win, part, (win == FrontWindow ())); + if (win == console_window) + { + resize_console_window (); + } +} + +resize_console_window () +{ + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + InvalRect (&console_window->portRect); +} + +close_window (win) +WindowPtr win; +{ +} + +pascal void +v_scroll_proc (ControlHandle control, short part) +{ + int oldval, amount = 0, newval; + int pagesize = ((*console_text)->viewRect.bottom - (*console_text)->viewRect.top) / (*console_text)->lineHeight; + if (part) + { + oldval = GetCtlValue (control); + switch (part) + { + case inUpButton: + amount = 1; + break; + case inDownButton: + amount = -1; + break; + case inPageUp: + amount = pagesize; + break; + case inPageDown: + amount = - pagesize; + break; + default: + /* (should freak out) */ + break; + } + SetCtlValue(control, oldval - amount); + newval = GetCtlValue (control); + amount = oldval - newval; + if (amount) + TEScroll (0, amount * (*console_text)->lineHeight, console_text); + } +} + +do_mouse_down (WindowPtr win, EventRecord *event) +{ + short part, value; + Point mouse; + ControlHandle control; + + if (1 /*is_app_window(win)*/) + { + SetPort (win); + mouse = event->where; + GlobalToLocal (&mouse); + part = FindControl(mouse, win, &control); + if (control == console_v_scrollbar) + { + switch (part) + { + case inThumb: + value = GetCtlValue (control); + part = TrackControl (control, mouse, nil); + if (part) + { + value -= GetCtlValue (control); + if (value) + TEScroll(0, value * (*console_text)->lineHeight, + console_text); + } + break; + default: +#if 0 /* don't deal with right now */ +#if 1 /* universal headers */ + value = TrackControl (control, mouse, (ControlActionUPP) v_scroll_proc); +#else + value = TrackControl (control, mouse, (ProcPtr) v_scroll_proc); +#endif +#endif + break; + } + } + else + { + TEClick (mouse, 0, console_text); + } + } +} + +scroll_text (hlines, vlines) +int hlines, vlines; +{ +} + +activate_window (win, activate) +WindowPtr win; +int activate; +{ + Rect grow_rect; + + if (win == nil) return; + /* It's convenient to make the activated window also be the + current GrafPort. */ + if (activate) + SetPort(win); + /* Activate the console window's scrollbar. */ + if (win == console_window) + { + if (activate) + { + TEActivate (console_text); + /* Cause the grow icon to be redrawn at the next update. */ + grow_rect = console_window->portRect; + grow_rect.top = grow_rect.bottom - sbarwid; + grow_rect.left = grow_rect.right - sbarwid; + InvalRect (&grow_rect); + } + else + { + TEDeactivate (console_text); + DrawGrowIcon (console_window); + } + HiliteControl (console_v_scrollbar, (activate ? 0 : 255)); + } +} + +update_window (win) +WindowPtr win; +{ + int controls = 1, growbox = 0; + GrafPtr oldport; + + /* Set the updating window to be the current grafport. */ + GetPort (&oldport); + SetPort (win); +/* recalc_depths(); */ + BeginUpdate (win); + if (win == console_window) + { + draw_console (); + controls = 1; + growbox = 1; + } + if (controls) + UpdateControls (win, win->visRgn); + if (growbox) + DrawGrowIcon (win); + EndUpdate (win); + SetPort (oldport); +} + +adjust_menus () +{ +} + +do_menu_command (which) +long which; +{ + short menuid, menuitem; + short itemHit; + Str255 daname; + short daRefNum; + Boolean handledbyda; + WindowPtr win; + short ditem; + int i; + char cmdbuf[300]; + + cmdbuf[0] = '\0'; + menuid = HiWord (which); + menuitem = LoWord (which); + switch (menuid) + { + case mApple: + switch (menuitem) + { + case miAbout: + Alert (128, nil); + break; +#if 0 + case miHelp: + /* (should pop up help info) */ + break; +#endif + default: + GetItem (GetMHandle (mApple), menuitem, daname); + daRefNum = OpenDeskAcc (daname); + } + break; + case mFile: + switch (menuitem) + { + case miFileNew: + if (console_window == FrontWindow ()) + { + close_window (console_window); + } + new_console_window (); + break; + case miFileOpen: + SysBeep (20); + break; + case miFileQuit: + ExitToShell (); + break; + } + break; + case mEdit: + /* handledbyda = SystemEdit(menuitem-1); */ + switch (menuitem) + { + case miEditCut: + TECut (console_text); + break; + case miEditCopy: + TECopy (console_text); + break; + case miEditPaste: + TEPaste (console_text); + break; + case miEditClear: + TEDelete (console_text); + break; + } + /* All of these operations need the same postprocessing. */ + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + break; + case mDebug: + switch (menuitem) + { + case miDebugTarget: + sprintf (cmdbuf, "target %s", "remote"); + break; + case miDebugRun: + sprintf (cmdbuf, "run"); + break; + case miDebugContinue: + sprintf (cmdbuf, "continue"); + break; + case miDebugStep: + sprintf (cmdbuf, "step"); + break; + case miDebugNext: + sprintf (cmdbuf, "next"); + break; + } + break; + } + HiliteMenu (0); + /* Execute a command if one had been given. Do here because a command + may longjmp before we get a chance to unhilite the menu. */ + if (strlen (cmdbuf) > 0) + execute_command (cmdbuf, 0); +} + +char commandbuf[1000]; + +do_keyboard_command (key) +int key; +{ + int startpos, endpos, i, len; + char *last_newline; + char buf[10], *text_str, *command, *cmd_start; + CharsHandle text; + + if (key == '\015' || key == '\003') + { + text = TEGetText (console_text); + HLock ((Handle) text); + text_str = *text; + startpos = (*console_text)->selStart; + endpos = (*console_text)->selEnd; + if (startpos != endpos) + { + len = endpos - startpos; + cmd_start = text_str + startpos; + } + else + { + for (i = startpos - 1; i >= 0; --i) + if (text_str[i] == '\015') + break; + last_newline = text_str + i; + len = (text_str + startpos) - 1 - last_newline; + cmd_start = last_newline + 1; + } + if (len > 1000) len = 999; + if (len < 0) len = 0; + strncpy (commandbuf + 1, cmd_start, len); + commandbuf[1 + len] = 0; + command = commandbuf + 1; + HUnlock ((Handle) text); + commandbuf[0] = strlen(command); + + /* Insert a newline and recalculate before doing any command. */ + key = '\015'; + TEKey (key, console_text); + TEInsert (buf, 1, console_text); + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + + if (strlen (command) > 0) + { + execute_command (command, 0); + bpstat_do_actions (&stop_bpstat); + } + } + else + { + /* A self-inserting character. This includes delete. */ + TEKey (key, console_text); + } +} + +/* Draw all graphical stuff in the console window. */ + +draw_console () +{ + SetPort (console_window); + TEUpdate (&(console_window->portRect), console_text); +} + +/* Cause an update of a given window's entire contents. */ + +force_update (win) +WindowPtr win; +{ + GrafPtr oldport; + + if (win == nil) return; + GetPort (&oldport); + SetPort (win); + EraseRect (&win->portRect); + InvalRect (&win->portRect); + SetPort (oldport); +} + +adjust_console_sizes () +{ + Rect tmprect; + + tmprect = console_window->portRect; + /* Move and size the scrollbar. */ + MoveControl (console_v_scrollbar, tmprect.right - sbarwid, 0); + SizeControl (console_v_scrollbar, sbarwid + 1, tmprect.bottom - sbarwid + 1); + /* Move and size the text. */ + tmprect.left += 7; + tmprect.right -= sbarwid; + tmprect.bottom -= sbarwid; + InsetRect(&tmprect, 1, 1); + (*console_text)->destRect = tmprect; + /* Fiddle bottom of viewrect to be even multiple of text lines. */ + tmprect.bottom = tmprect.top + + ((tmprect.bottom - tmprect.top) / (*console_text)->lineHeight) + * (*console_text)->lineHeight; + (*console_text)->viewRect = tmprect; +} + +adjust_console_scrollbars () +{ + int lines, newmax, value; + + (*console_v_scrollbar)->contrlVis = 0; + lines = (*console_text)->nLines; + newmax = lines - (((*console_text)->viewRect.bottom + - (*console_text)->viewRect.top) + / (*console_text)->lineHeight); + if (newmax < 0) newmax = 0; + SetCtlMax (console_v_scrollbar, newmax); + value = ((*console_text)->viewRect.top - (*console_text)->destRect.top) + / (*console_text)->lineHeight; + SetCtlValue (console_v_scrollbar, value); + (*console_v_scrollbar)->contrlVis = 0xff; + ShowControl (console_v_scrollbar); +} + +/* Scroll the TE record so that it is consistent with the scrollbar(s). */ + +adjust_console_text () +{ + TEScroll (((*console_text)->viewRect.left + - (*console_text)->destRect.left) + - 0 /* get h scroll value */, + ((((*console_text)->viewRect.top - (*console_text)->destRect.top) + / (*console_text)->lineHeight) + - GetCtlValue (console_v_scrollbar)) + * (*console_text)->lineHeight, + console_text); +} + +/* Readline substitute. */ + +char * +readline (char *prrompt) +{ + return gdb_readline (prrompt); +} + +char *rl_completer_word_break_characters; + +char *rl_completer_quote_characters; + +int (*rl_completion_entry_function) (); + +int rl_point; + +char *rl_line_buffer; + +char *rl_readline_name; + +/* History substitute. */ + +void +add_history (char *buf) +{ +} + +void +stifle_history (int n) +{ +} + +int +unstifle_history () +{ +} + +int +read_history (char *name) +{ +} + +int +write_history (char *name) +{ +} + +int +history_expand (char *x, char **y) +{ +} + +extern HIST_ENTRY * +history_get (int xxx) +{ + return NULL; +} + +int history_base; + +char * +filename_completion_function (char *text, char *name) +{ + return "?"; +} + +char * +tilde_expand (char *str) +{ + return strsave (str); +} + +/* Modified versions of standard I/O. */ + +#undef fprintf + +int +hacked_fprintf (FILE *fp, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + if (mac_app && (fp == stdout || fp == stderr)) + { + char buf[1000]; + + ret = vsprintf(buf, fmt, ap); + TEInsert (buf, strlen(buf), console_text); + } + else + ret = vfprintf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#undef printf + +int +hacked_printf (const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = hacked_vfprintf(stdout, fmt, ap); + va_end (ap); + return ret; +} + +#undef vfprintf + +int +hacked_vfprintf (FILE *fp, const char *format, va_list args) +{ + if (mac_app && (fp == stdout || fp == stderr)) + { + char buf[1000]; + int ret; + + ret = vsprintf(buf, format, args); + TEInsert (buf, strlen(buf), console_text); + if (strchr(buf, '\n')) + { + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + } + return ret; + } + else + return vfprintf (fp, format, args); +} + +#undef fputs + +hacked_fputs (const char *s, FILE *fp) +{ + if (mac_app && (fp == stdout || fp == stderr)) + { + TEInsert (s, strlen(s), console_text); + if (strchr(s, '\n')) + { + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + } + return 0; + } + else + return fputs (s, fp); +} + +#undef fputc + +hacked_fputc (const char c, FILE *fp) +{ + if (mac_app && (fp == stdout || fp == stderr)) + { + char buf[1]; + + buf[0] = c; + TEInsert (buf, 1, console_text); + if (c == '\n') + { + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + } + return c; + } + else + return fputc (c, fp); +} + +#undef putc + +hacked_putc (const char c, FILE *fp) +{ + if (mac_app && (fp == stdout || fp == stderr)) + { + char buf[1]; + + buf[0] = c; + TEInsert (buf, 1, console_text); + if (c == '\n') + { + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + } + return c; + } + else + return fputc (c, fp); +} + +#undef fflush + +hacked_fflush (FILE *fp) +{ + if (mac_app && (fp == stdout || fp == stderr)) + { + adjust_console_sizes (); + adjust_console_scrollbars (); + adjust_console_text (); + return 0; + } + return fflush (fp); +} + +#undef fgetc + +hacked_fgetc (FILE *fp) +{ + if (mac_app && (fp == stdin)) + { + /* Catch any attempts to use this. */ + DebugStr("\pShould not be reading from stdin!"); + return '\n'; + } + return fgetc (fp); +} |