b8ec8d4ab0
(SiowGDB): New target, GDB using SIOW library. (init-new.c): New target, attempt to generate init.c from sources. (main.c.o, top.c.o): Put each in its own segment. * main.c (main) [MPW]: Always call mac_init. * utils.c (query) [MPW]: Always return "yes" if in MacGDB, output an extra newline otherwise. * mac-xdep.c: More comments in various places, remove junk. (mac_init): Add tests for MPW and SIOW. (use_wne, has_color_qd): Renamed. (use_color_qd): New variable. (grow_window): Only do console resizing to console window, call resize_console_window. (zoom_window): Call resize_console_window. (resize_console_window, scroll_text): New functions. (adjust_console_sizes): Always align viewrect to even multiples of text lines. (adjust_console_text): Always scroll by whole lines. (hacked_vfprintf, hacked_puts, hacked_fputc, hacked_putc): Force a recalculation of scroll positions if a newline was output. (hacked_fflush): Similarly, for flushing. (hacked_fgetc): New function, aborts if called in MacGDB. * ser-mac.c (mac_readchar): Rename starttime to start_time, remove debugging printf. (mac_write): Sleep on first 4 writes. (sec_sleep): New function, works like standard sleep. * macgdb.r: Adjust positioning and contents of About box. Set minimum size to 2000K, preferred size to 5000K. * config/m68k/xm-mpw.h (fgetc): Define as a macro.
1075 lines
22 KiB
C
1075 lines
22 KiB
C
/* 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
#include "defs.h"
|
|
|
|
#include "readline.h"
|
|
#include "history.h"
|
|
|
|
#include <Values.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 <GestaltEqu.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
|
|
|
|
#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"
|
|
|
|
/* 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;
|
|
Boolean gotevent;
|
|
Point mouse;
|
|
EventRecord event;
|
|
WindowPtr win;
|
|
RgnHandle cursorRgn;
|
|
int i;
|
|
Handle menubar;
|
|
MenuHandle menu;
|
|
Handle siow_resource;
|
|
|
|
mac_app = 0;
|
|
|
|
/* 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:
|
|
value = TrackControl (control, mouse, (ProcPtr) v_scroll_proc);
|
|
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. */
|
|
|
|
#include <stdarg.h>
|
|
|
|
#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);
|
|
}
|