mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-08 23:53:31 +02:00
autotools
dox2-src
help
images
include
lib-src
FileDialog
expat
ffmpeg
lame
lib-widget-extra
libflac
libid3tag
libmad
libnyquist
autotools
nyquist
cmt
ffts
nyqsrc
nyqstk
sys
mac
MacAE.c
MacCommandWin.c
MacCommandWin.h
MacDrag.h
MacFileUtils.c
MacFileUtils.h
MacGlobals.h
MacHandleEv.c
MacHandleEv.h
README.txt
macaboutbox.c
macaboutbox.h
macdrag.c
macfun.c
macint.c
macint.h
macptrs.h
macstuff.c
macstuff.h
sndsystem.h
switches.h
system.lsp
xlextstart.c
unix
win
tran
xlisp
Readme.txt
license.txt
LICENSE.txt
Makefile.am
Makefile.in
README.txt
configure
configure.ac
nyquist.patch
nyx.c
nyx.h
revert-convolve.patch
sound.patch
xlextstart.c
xlisp.patch
libogg
libscorealign
libsndfile
libsoxr
libvamp
libvorbis
lv2
mod-null
mod-nyq-bench
mod-script-pipe
mod-track-panel
portaudio-v19
portburn
portmidi
portmixer
portsmf
sbsms
soundtouch
twolame
Makefile.am
Makefile.in
audacity-patches.txt
dist-libsoxr.mk
dist-libvamp.mk
dist-portaudio.mk
locale
m4
mac
nyquist
plug-ins
presets
qa
scripts
src
tests
win
.gitignore
.travis.yml
ABOUT-NLS
LICENSE.txt
Makefile.am
Makefile.in
README.txt
audacity.dox
branches.txt
configure
configure.ac
po
todo.txt
765 lines
29 KiB
C
765 lines
29 KiB
C
//=============================================================================
|
|
// All command window updates, input, etc happen here -EAD
|
|
//=============================================================================
|
|
#include <Controls.h>
|
|
/* #include <ControlDefinitions.h> */
|
|
#include <Events.h>
|
|
#include <Fonts.h>
|
|
#include <MacWindows.h>
|
|
#include "MacGlobals.h"
|
|
#include "macint.h"
|
|
#include <ctype.h>
|
|
#define NIL ((void *) 0)
|
|
|
|
//=============================================================================
|
|
// local variables
|
|
//=============================================================================
|
|
|
|
ControlHandle vScroll;
|
|
int cursorPos; /* the cursor's position on the line */
|
|
short linesInView; /* how many lines are in the window */
|
|
int cmdStart; /* where (in text record) the current command starts */
|
|
TextStyle textStyle[2]; /* styles: bold for user input, plain for output */
|
|
/* output is buffered */
|
|
Handle hOutputBuffer = NULL;
|
|
enum currentStyle { plainStyle, boldStyle } currentStyle;
|
|
|
|
static void GoStartOfLine (void);
|
|
static void GoEndOfLine (void);
|
|
static void GoBackOneWord (void);
|
|
static void GoForwardOneWord (void);
|
|
|
|
//=============================================================================
|
|
// static void DoScrollBar (ControlHandle control, short change)
|
|
//=============================================================================
|
|
/* keep track of the user as he fiddles with the scroll bar */
|
|
/* This routine is called while the user has the mouse down. */
|
|
/* It makes sure the thumb isn't dragged out-of-bounds. */
|
|
//=============================================================================
|
|
|
|
static void DoScrollBar (ControlHandle control, short change) {
|
|
short value = GetControlValue (control), max = GetControlMaximum (control);
|
|
long newval = value + change; /* this is a long in case we try to go past MAX_INT */
|
|
if (newval < 0) newval = 0; else if (newval > max) newval = max;
|
|
SetControlValue (control, (short) newval);
|
|
if (newval != value) TEScroll (0, (short) (value - newval) * LINEHEIGHT, hTERec);
|
|
}
|
|
|
|
//=============================================================================
|
|
// pascal Boolean ScrollClickLoop (void)
|
|
//=============================================================================
|
|
//
|
|
//=============================================================================
|
|
|
|
pascal Boolean ScrollClickLoop (void) {
|
|
Rect tempRect;
|
|
Point mouse;
|
|
GrafPtr oldPort;
|
|
RgnHandle oldClip;
|
|
short amount = 0;
|
|
|
|
if (FrontWindow () != gCommandWin) return false;
|
|
|
|
GetPort (&oldPort);
|
|
SetPort (gCommandWin);
|
|
GetClip (oldClip = NewRgn ());
|
|
SetRect (&tempRect, INT_MIN, INT_MIN, INT_MAX, INT_MAX);
|
|
ClipRect (&tempRect);
|
|
|
|
GetMouse (&mouse);
|
|
if (mouse.v < TEXTREC->viewRect.top) DoScrollBar (vScroll, -1);
|
|
else if (mouse.v > TEXTREC->viewRect.bottom) DoScrollBar (vScroll, 1);
|
|
|
|
SetClip (oldClip);
|
|
DisposeRgn (oldClip);
|
|
SetPort (oldPort);
|
|
return true;
|
|
}
|
|
|
|
//=============================================================================
|
|
// static pascal void ScrollProc (ControlHandle control, short thePart)
|
|
//=============================================================================
|
|
// for clicks in the scroll bar or arrows; update the window properly
|
|
//=============================================================================
|
|
|
|
pascal void ScrollProc (ControlHandle control, short thePart) {
|
|
short amount;
|
|
WindowPtr window;
|
|
|
|
if (!thePart) return;
|
|
window = (*control)->contrlOwner;
|
|
switch (thePart) {
|
|
case kControlUpButtonPart: amount = -1; break;
|
|
case kControlDownButtonPart: amount = 1; break;
|
|
case kControlPageUpPart: amount = -linesInView; break;
|
|
case kControlPageDownPart: amount = linesInView; break;
|
|
}
|
|
DoScrollBar (control, amount);
|
|
}
|
|
|
|
//=============================================================================
|
|
// Rect SetTERect (void)
|
|
//=============================================================================
|
|
// set the dimensions of the text record in its window
|
|
//=============================================================================
|
|
|
|
Rect SetTERect (void) {
|
|
Rect teRect = gCommandWin->portRect;
|
|
teRect.right -= SCROLLER_WIDTH;
|
|
InsetRect (&teRect, TEXT_MARGIN, TEXT_MARGIN);
|
|
linesInView = (teRect.bottom - teRect.top) / LINEHEIGHT;
|
|
teRect.bottom = teRect.top + linesInView * LINEHEIGHT; /* round off */
|
|
return teRect;
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void AdjustCursor (EventRecord *theEvent)
|
|
//=============================================================================
|
|
// make the pointer an I-beam iff it's in the text window
|
|
//=============================================================================
|
|
|
|
void AdjustCursor (Point theLoc, RgnHandle theRgn)
|
|
{
|
|
RgnHandle arrowRgn, iBeamRgn, hiliteRgn, tempRgn;
|
|
Rect theRect;
|
|
Point thePoint;
|
|
|
|
if (gInBackground)
|
|
return;
|
|
|
|
arrowRgn = NewRgn();
|
|
SetRectRgn(arrowRgn, -32767, -32767, 32767, 32767);
|
|
|
|
// GlobalToLocal ((theLoc); ???
|
|
|
|
if (gCommandWin == FrontWindow () ) {
|
|
SetPort(gCommandWin);
|
|
iBeamRgn = NewRgn();
|
|
hiliteRgn = NewRgn();
|
|
|
|
theRect = TEXTREC->viewRect;
|
|
LocalToGlobal((Point *)&(theRect.top));
|
|
LocalToGlobal((Point *)&(theRect.bottom));
|
|
RectRgn(iBeamRgn, &theRect);
|
|
|
|
TEGetHiliteRgn(hiliteRgn, hTERec);
|
|
thePoint.h = thePoint.v = 0;
|
|
LocalToGlobal(&thePoint);
|
|
OffsetRgn(hiliteRgn, thePoint.h, thePoint.v);
|
|
|
|
DiffRgn(arrowRgn, hiliteRgn, arrowRgn);
|
|
DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
|
|
|
|
DiffRgn(iBeamRgn, hiliteRgn, iBeamRgn);
|
|
|
|
if (PtInRgn(theLoc, iBeamRgn)) {
|
|
SetCursor(*GetCursor(iBeamCursor));
|
|
CopyRgn(iBeamRgn, theRgn);
|
|
} else if (PtInRgn(theLoc, hiliteRgn)) {
|
|
SetCursor(&qd.arrow);
|
|
CopyRgn(hiliteRgn, theRgn);
|
|
} else {
|
|
SetCursor(&qd.arrow);
|
|
CopyRgn(arrowRgn, theRgn);
|
|
}
|
|
|
|
DisposeRgn(iBeamRgn);
|
|
DisposeRgn(hiliteRgn);
|
|
|
|
} else {
|
|
SetCursor(&qd.arrow);
|
|
CopyRgn(arrowRgn, theRgn);
|
|
}
|
|
|
|
DisposeRgn(arrowRgn);
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// static void SetScrollRect (void)
|
|
//=============================================================================
|
|
// Set Scroll bar rec size
|
|
//=============================================================================
|
|
|
|
void SetScrollRect (void) {
|
|
/* set the dimensions of the scroll bar in its window */
|
|
|
|
// This change fixes the double flash on window resize -EAD
|
|
|
|
// MoveControl (vScroll, commandWin->portRect.right - SCROLLER_WIDTH, -1);
|
|
// SizeControl (vScroll, SCROLLER_WIDTH + 1,
|
|
// (commandWin->portRect.bottom - commandWin->portRect.top) - (SCROLLER_WIDTH - 2));
|
|
(*vScroll)->contrlRect.left = gCommandWin->portRect.right - SCROLLER_WIDTH;
|
|
(*vScroll)->contrlRect.top = -1;
|
|
(*vScroll)->contrlRect.right = gCommandWin->portRect.right + 1;
|
|
(*vScroll)->contrlRect.bottom = gCommandWin->portRect.bottom - (SCROLLER_WIDTH - 1);
|
|
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void AdjustScrollBar (void)
|
|
//=============================================================================
|
|
// Set the thumb on scrollbar
|
|
//=============================================================================
|
|
|
|
static void AdjustScrollBar (void) {
|
|
/* adjust the scroll bar to match the position of the text view */
|
|
short oldval = GetControlValue (vScroll), oldmax = GetControlMaximum (vScroll);
|
|
short value, max;
|
|
short test;
|
|
|
|
max = TEXTREC->nLines - linesInView;
|
|
if ((TEXTREC->teLength > 0) && (*(*TEXTREC->hText + TEXTREC->teLength - 1) == '\r')) max++;
|
|
if (max < 0) max = 0;
|
|
if (max != oldmax) SetControlMaximum (vScroll, max);
|
|
value = (short)((TEXTREC->viewRect.top - TEXTREC->destRect.top) / LINEHEIGHT);
|
|
// value = roundup ((TEXTREC->viewRect.top - TEXTREC->destRect.top) / LINEHEIGHT);
|
|
if (value < 0) value = 0; else if (value > max) value = max;
|
|
if (value != oldval) SetControlValue (vScroll, value);
|
|
}
|
|
|
|
static short roundup (float x) { /* a kludge to round up a float to an int */
|
|
if (((int) x) != ((int) (x += 0.5))) x += 0.5;
|
|
return (int) x;
|
|
}
|
|
|
|
//=============================================================================
|
|
// void DoKeyPress (EventRecord *theEvent)
|
|
//=============================================================================
|
|
// Hanlde Keyboard Input
|
|
//=============================================================================
|
|
|
|
void DoKeyPress (EventRecord *theEvent) {
|
|
short whatKey = theEvent->message & charCodeMask;
|
|
if (theEvent->modifiers & cmdKey) {
|
|
long choice;
|
|
AdjustMenus ();
|
|
if (choice = MenuKey (theEvent->message)) DoMenu (choice);
|
|
else if (((whatKey == 'w') || (whatKey == 'W')) && (FrontWindow () == gGraphicsWin))
|
|
HideGrafWin ();
|
|
else if (whatKey == LEFTARROW) GoStartOfLine ();
|
|
else if (whatKey == RIGHTARROW) GoEndOfLine ();
|
|
else if (whatKey == UPARROW) DoScrollBar (vScroll, - linesInView);
|
|
else if (whatKey == DOWNARROW) DoScrollBar (vScroll, linesInView);
|
|
}
|
|
else if (theEvent->modifiers & optionKey) {
|
|
if (whatKey == LEFTARROW) GoBackOneWord ();
|
|
else if (whatKey == RIGHTARROW) GoForwardOneWord ();
|
|
}
|
|
else switch (whatKey) {
|
|
case PAGEUP: DoScrollBar (vScroll, -linesInView); break;
|
|
case PAGEDN: DoScrollBar (vScroll, linesInView); break;
|
|
case HOMEKEY: DoScrollBar (vScroll, INT_MIN); break;
|
|
case ENDKEY: DoScrollBar (vScroll, INT_MAX); break;
|
|
case FNKEY: break;
|
|
case HELPKEY: break;
|
|
default: recentChar = theEvent->message & charCodeMask;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void DrawOnlyGrowIcon (WindowPtr window)
|
|
//=============================================================================
|
|
// draw growbox on command window with no scoll bars
|
|
//=============================================================================
|
|
|
|
static void DrawOnlyGrowIcon (WindowPtr window)
|
|
{
|
|
RgnHandle saveRgn;
|
|
Rect growRect;
|
|
|
|
growRect = window->portRect;
|
|
growRect.top = growRect.bottom - SCROLLER_WIDTH;
|
|
growRect.left = growRect.right - SCROLLER_WIDTH;
|
|
GetClip (saveRgn = NewRgn ());
|
|
ClipRect (&growRect);
|
|
DrawGrowIcon (window);
|
|
SetClip (saveRgn);
|
|
DisposeRgn (saveRgn);
|
|
}
|
|
|
|
//=============================================================================
|
|
// void SetSelection (short start, short end)
|
|
//=============================================================================
|
|
// set text selection in the command window
|
|
//=============================================================================
|
|
|
|
void SetSelection (short start, short end) {
|
|
TEXTREC->clikStuff = 255; /* to make sure the caret appears at the start of a line when it should */
|
|
/* see tech note "TextEdit EOL Ambiguity" for more information */
|
|
TESetSelect (start, end, hTERec);
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void CancelFlash (void)
|
|
//=============================================================================
|
|
// cancel the matching-paren flashing
|
|
//=============================================================================
|
|
|
|
static void CancelFlash (void) {
|
|
if (flashTime) {
|
|
flashTime = 0;
|
|
SetSelection (cursorBeforeFlash, cursorBeforeFlash);
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void StopPasting (void)
|
|
//=============================================================================
|
|
// clean up after finishing a paste
|
|
//=============================================================================
|
|
|
|
void StopPasting (void) {
|
|
pastedLength = 0;
|
|
if (pastedTextH) {
|
|
DisposeHandle (pastedTextH);
|
|
pastedTextH = NULL;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void DoStyle (int whatStyle)
|
|
//=============================================================================
|
|
// set the text to a certain style
|
|
//=============================================================================
|
|
|
|
static void DoStyle (int whatStyle) {
|
|
TESetStyle (doFace, &(textStyle[whatStyle]), false, hTERec);
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void FlushOutput (void)
|
|
//=============================================================================
|
|
// clear out the output buffer, dumping its contents to the window
|
|
//=============================================================================
|
|
|
|
void FlushOutput (void) {
|
|
short totalLines, scrollAmount, max;
|
|
|
|
if (outputBufferLength == 0) return;
|
|
CancelFlash ();
|
|
DoStyle (plainStyle);
|
|
HLock (hOutputBuffer);
|
|
TEInsert (*hOutputBuffer, outputBufferLength, hTERec);
|
|
HUnlock (hOutputBuffer);
|
|
outputBufferLength = 0;
|
|
|
|
if (TEXTREC->teLength > SCROLLBACK_THRESHHOLD) {
|
|
/* make sure TE record isn't too long */
|
|
#ifdef ORIGINALCODE
|
|
/* I replaced this because Nyquist was crashing after the
|
|
buffer got filled. The replacement below is simpler and
|
|
eliminates the crashes, although it probably could cause
|
|
problems by clearing the selection.
|
|
*/
|
|
int i = 1, newLength;
|
|
TEPtr textPtr;
|
|
while ((TEXTREC->teLength - TEXTREC->lineStarts[i]) >
|
|
(SCROLLBACK_THRESHHOLD - DELETE_BLOCK)) i++;
|
|
i = TEXTREC->lineStarts[i];
|
|
newLength = TEXTREC->teLength - i;
|
|
textPtr = (TEPtr)(*(TEXTREC->hText));
|
|
BlockMoveData ((Ptr)((long)textPtr + i), textPtr, newLength);
|
|
SetHandleSize (TEXTREC->hText, newLength);
|
|
TEXTREC->destRect.top += LINEHEIGHT;
|
|
TECalText (hTERec);
|
|
TEUpdate (&(TEXTREC->viewRect), hTERec);
|
|
#else
|
|
/* find the line start after DELETE_BLOCK */
|
|
int i = 1;
|
|
while (TEXTREC->lineStarts[i] < DELETE_BLOCK) i++;
|
|
TESetSelect(0, TEXTREC->lineStarts[i], hTERec);
|
|
TEDelete(hTERec);
|
|
/* after deletion, put cursor back at end of buffer */
|
|
TESetSelect(TEXTREC->teLength, TEXTREC->teLength, hTERec);
|
|
#endif
|
|
}
|
|
TESelView (hTERec);
|
|
AdjustScrollBar ();
|
|
}
|
|
|
|
//=============================================================================
|
|
// void PrepareForInput (void)
|
|
//=============================================================================
|
|
// get ready to take input
|
|
//=============================================================================
|
|
|
|
void PrepareForInput (void) {
|
|
FlushOutput ();
|
|
cmdStart = TEXTREC->selStart;
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void DeleteRange (void)
|
|
//=============================================================================
|
|
// delete the selected range of text, updating cmdStart as necessary
|
|
//=============================================================================
|
|
|
|
void DeleteRange (void) {
|
|
if (TEXTREC->selEnd <= cmdStart) return;
|
|
if (TEXTREC->selStart < cmdStart) SetSelection (cmdStart, TEXTREC->selEnd);
|
|
TEDelete (hTERec);
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void CopyThisLineToEnd (void)
|
|
//=============================================================================
|
|
// copy the line the caret is on to the end
|
|
//=============================================================================
|
|
|
|
static void CopyThisLineToEnd (void) {
|
|
char *buffer;
|
|
short b, i, caretOffset;
|
|
|
|
/* first find out exactly where it starts */
|
|
i = TEXTREC->nLines-1; /* first find which line */
|
|
while (TEXTREC->selStart < TEXTREC->lineStarts[i]) i--;
|
|
while ((i > 0) && ((*(TEXTREC->hText))[TEXTREC->lineStarts[i]-1] != '\r'))
|
|
i--; /* for wrapped lines */
|
|
i = TEXTREC->lineStarts[i]; /* now zero in on the exact character where it begins */
|
|
while ((TEXTCHAR(i) >= '0') && (TEXTCHAR(i) <= '9')) i++; /* skip error level */
|
|
if ((TEXTCHAR(i) == '>') && (TEXTCHAR(i+1) == ' ')) i+=2; /* get rid of leading prompt */
|
|
|
|
caretOffset = TEXTREC->selStart - i; /* how many characters in is the caret? */
|
|
|
|
/* now put the line into the buffer */
|
|
b = 0;
|
|
while ((TEXTCHAR(i+b) != '\r') && (i+b < TEXTREC->teLength)) b++; /* find the end of the line */
|
|
buffer = (char *) NewPtr (b);
|
|
BlockMoveData (*TEXTREC->hText + i, buffer, b);
|
|
buffer[b] = '\0';
|
|
|
|
/* delete whatever's already on the last line */
|
|
SetSelection (cmdStart, TEXTREC->teLength);
|
|
TEDelete (hTERec);
|
|
|
|
DoStyle (boldStyle);
|
|
TEInsert (buffer, b, hTERec);
|
|
DisposePtr (buffer);
|
|
|
|
if (caretOffset < 0) caretOffset = b;
|
|
SetSelection (cmdStart + caretOffset, cmdStart + caretOffset);
|
|
}
|
|
|
|
//=============================================================================
|
|
// Next four functions possition cursor in text
|
|
//=============================================================================
|
|
|
|
static void GoStartOfLine (void) {
|
|
short whichLine = TEXTREC->nLines - 1; /* look for the caret; start at the end and go up */
|
|
while (TEXTREC->lineStarts[whichLine] > TEXTREC->selStart) whichLine--;
|
|
SetSelection (TEXTREC->lineStarts[whichLine], TEXTREC->lineStarts[whichLine]);
|
|
AdjustScrollBar ();
|
|
}
|
|
|
|
static void GoEndOfLine (void) {
|
|
short whichLine = TEXTREC->nLines - 1; /* look for the caret; start at the end and go up */
|
|
while (TEXTREC->lineStarts[whichLine] > TEXTREC->selStart) whichLine--;
|
|
if (whichLine == TEXTREC->nLines - 1)
|
|
SetSelection (TEXTREC->teLength, TEXTREC->teLength);
|
|
else SetSelection (TEXTREC->lineStarts[whichLine+1] - 1, TEXTREC->lineStarts[whichLine+1] - 1);
|
|
AdjustScrollBar ();
|
|
}
|
|
|
|
static void GoBackOneWord (void) {
|
|
short i = TEXTREC->selStart;
|
|
while ((i > 0) && !isalnum (TEXTCHAR(i-1))) i--;
|
|
while ((i > 0) && isalnum (TEXTCHAR(i-1))) i--;
|
|
SetSelection (i, i);
|
|
}
|
|
|
|
static void GoForwardOneWord (void) {
|
|
short i = TEXTREC->selStart;
|
|
while ((i < TEXTREC->teLength) && !isalnum (TEXTCHAR(i))) i++;
|
|
while ((i < TEXTREC->teLength) && isalnum (TEXTCHAR(i))) i++;
|
|
SetSelection (i, i);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// static void EditFreely (void)
|
|
//=============================================================================
|
|
// Enter text into the command windows
|
|
//=============================================================================
|
|
|
|
static void EditFreely (void) {
|
|
Boolean done;
|
|
do {
|
|
done = false;
|
|
DoEvent ();
|
|
if (pastedLength > 0) { /* if there is still text to paste, paste it */
|
|
int i = 0;
|
|
CancelFlash ();
|
|
if (TEXTREC->selStart < cmdStart) StopPasting ();
|
|
else {
|
|
while ((i < pastedLength) && (((char *)(*pastedTextH))[i] != '\r')) i++;
|
|
DoStyle (boldStyle);
|
|
TEInsert (*pastedTextH, i, hTERec);
|
|
AdjustScrollBar ();
|
|
if (i < pastedLength) { /* we were stopped by a carriage return, so eat it */
|
|
i++;
|
|
done = true;
|
|
}
|
|
pastedLength -= i;
|
|
if (pastedLength > 0) {
|
|
BlockMoveData ((Ptr)((long)(*pastedTextH) + i), *pastedTextH, pastedLength);
|
|
SetHandleSize (pastedTextH, pastedLength);
|
|
} else StopPasting ();
|
|
}
|
|
}
|
|
else if (recentChar) { /* if the last event got us a character, process it */
|
|
int i;
|
|
Boolean wasOnLastLine;
|
|
CancelFlash ();
|
|
|
|
if ((TEXTREC->selEnd <= cmdStart) && (TEXTREC->selStart != TEXTREC->selEnd)) continue;
|
|
if (TEXTREC->selStart < cmdStart) SetSelection (cmdStart, TEXTREC->selEnd);
|
|
wasOnLastLine = (TEXTREC->selStart >= cmdStart);
|
|
|
|
if ((recentChar & 0xfc) == 0x1c) { /* was this an arrow key? */
|
|
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
|
|
TEKey (recentChar, hTERec);
|
|
AdjustScrollBar ();
|
|
continue;
|
|
}
|
|
if (!wasOnLastLine) CopyThisLineToEnd ();
|
|
switch (recentChar) {
|
|
case FWDDEL:
|
|
if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
|
|
else if ((TEXTREC->selStart >= cmdStart) && (TEXTREC->selStart < TEXTREC->teLength)) {
|
|
TEDeactivate (hTERec);
|
|
SetSelection (TEXTREC->selStart, TEXTREC->selStart + 1);
|
|
TEDelete (hTERec);
|
|
if (FrontWindow () == gCommandWin) TEActivate (hTERec);
|
|
}
|
|
break;
|
|
case CLRKEY:
|
|
if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
|
|
break;
|
|
case DELETE:
|
|
if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
|
|
else if (TEXTREC->selStart > cmdStart) {
|
|
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
|
|
TEKey (DELETE, hTERec);
|
|
}
|
|
break;
|
|
case RETURN:
|
|
if (wasOnLastLine) done = true;
|
|
break;
|
|
case ENTER: /* ENTER ends command no matter what */
|
|
done = true;
|
|
break;
|
|
default:
|
|
DoStyle (boldStyle);
|
|
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
|
|
TEKey (recentChar, hTERec);
|
|
if ((recentChar == ')') && (TEXTREC->selStart > cmdStart)) {
|
|
short parenCount = -1;
|
|
Boolean inQuotes = false;
|
|
i = TEXTREC->selStart - 1;
|
|
while ((--i >= cmdStart) && (parenCount != 0))
|
|
switch ((*TEXTREC->hText)[i]) {
|
|
case DBLQUOTE: inQuotes = !inQuotes; break;
|
|
case '(': if (!inQuotes) parenCount++; break;
|
|
case ')': if (!inQuotes) parenCount--; break;
|
|
}
|
|
if (parenCount == 0) {
|
|
cursorBeforeFlash = TEXTREC->selStart;
|
|
SetSelection (i+1, i+2); /* flash the matching open-paren */
|
|
flashTime = 10;
|
|
}
|
|
} else if ((recentChar == DBLQUOTE) && (TEXTREC->selStart > cmdStart)) {
|
|
i = TEXTREC->selStart - 1;
|
|
while ((--i >= cmdStart) && ((*TEXTREC->hText)[i] != DBLQUOTE)) ;
|
|
if ((*TEXTREC->hText)[i] == DBLQUOTE) {
|
|
cursorBeforeFlash = TEXTREC->selStart;
|
|
SetSelection (i, i+1); /* flash the matching double-quote */
|
|
flashTime = 10;
|
|
}
|
|
}
|
|
}
|
|
AdjustScrollBar ();
|
|
}
|
|
} while (!done);
|
|
}
|
|
|
|
char *macgets (void) {
|
|
/* retrieve a typed character */
|
|
/* Note that this uses some extensive (and clever, if I may say so myself) buffering. */
|
|
int i, b, bufSize;
|
|
char *ptr, *buffer;
|
|
Boolean done, onLastLine;
|
|
|
|
PrepareForInput ();
|
|
do { /* repeat until a full expression has been typed */
|
|
EditFreely (); /* allow free editing for a while */
|
|
|
|
/* Now, we have a complete command to parse, if and only if: */
|
|
/* - the cursor was on the last line when the user pressed Return or Enter, and */
|
|
/* - the user either pressed Enter, or else every '(' since the beginning */
|
|
/* of the command is matched by a ')'. */
|
|
/* Quoting is watched for. ( ") is not a complete expression. */
|
|
|
|
done = true;
|
|
if (TEXTREC->selStart != TEXTREC->teLength) /* if we're not at the end already */
|
|
SetSelection (TEXTREC->teLength, TEXTREC->teLength); /* send cursor to end */
|
|
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
|
|
TEKey ('\r', hTERec);
|
|
|
|
/* check and see if we've completed the command yet */
|
|
if (recentChar != ENTER) {
|
|
Boolean inQuotes = false;
|
|
short parenCount = 0;
|
|
for (i = cmdStart; i < TEXTREC->teLength; i++)
|
|
switch ((*TEXTREC->hText)[i]) {
|
|
case DBLQUOTE: inQuotes = !inQuotes; break;
|
|
case '(': if (!inQuotes) parenCount++; break;
|
|
case ')': if (!inQuotes) parenCount--; break;
|
|
}
|
|
if ((parenCount > 0) || inQuotes) done = false;
|
|
}
|
|
|
|
AdjustScrollBar ();
|
|
} while (!done);
|
|
|
|
/* put the entire command into the buffer, and return it */
|
|
bufSize = TEXTREC->teLength - cmdStart;
|
|
buffer = (char *) NewPtr (bufSize + 1);
|
|
BlockMoveData (*TEXTREC->hText + cmdStart, buffer, bufSize);
|
|
buffer[bufSize] = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
void macputc (int ch) {
|
|
/* put a char into the output buffer, and flush the buffer if necessary */
|
|
switch (ch) {
|
|
case '\t':
|
|
do { macputc (' '); } while (cursorPos & 7);
|
|
break;
|
|
case DELETE:
|
|
if (cursorPos) cursorPos--; /* and fall through to default */
|
|
default:
|
|
if (outputBufferLength == MAX_BUF) FlushOutput ();
|
|
if (ch == '\n') {
|
|
cursorPos = 0;
|
|
(*hOutputBuffer)[outputBufferLength++] = '\r';
|
|
} else {
|
|
cursorPos++;
|
|
(*hOutputBuffer)[outputBufferLength++] = ch;
|
|
}
|
|
}
|
|
}
|
|
|
|
void macputs (char *s) {
|
|
/* for completeness */
|
|
while (*s) macputc (*s++);
|
|
}
|
|
|
|
void scrflush (void) {
|
|
extern void osflush (void);
|
|
/* clear out everything */
|
|
FlushOutput ();
|
|
osflush ();
|
|
}
|
|
|
|
void scrclear (void) {
|
|
/* clear text window -- not implemented */
|
|
}
|
|
|
|
//=============================================================================
|
|
// static void UpdateCmdWindow (void)
|
|
//=============================================================================
|
|
// main command window update procedure
|
|
//=============================================================================
|
|
|
|
|
|
void UpdateCmdWindow (void) {
|
|
long textBottom;
|
|
Rect tempRect;
|
|
|
|
InvalRect (&(gCommandWin->portRect));
|
|
BeginUpdate (gCommandWin);
|
|
BlockMoveData(&(gCommandWin->portRect), &tempRect, sizeof(Rect));
|
|
tempRect.right -= SCROLLER_WIDTH;
|
|
EraseRect (&tempRect);
|
|
if (gCommandWinResized) {
|
|
TEXTREC->viewRect = SetTERect ();
|
|
TEXTREC->destRect.right = TEXTREC->viewRect.right;
|
|
TECalText (hTERec);
|
|
SetScrollRect ();
|
|
gCommandWinResized = false;
|
|
}
|
|
DrawOnlyGrowIcon (gCommandWin);
|
|
FlushOutput ();
|
|
|
|
TEXTREC->viewRect = SetTERect (); /* adjust for possible change in height of status line */
|
|
|
|
textBottom = TEXTREC->destRect.top + (TEXTREC->nLines * LINEHEIGHT);
|
|
if (TEXTREC->destRect.top > TEXTREC->viewRect.top)
|
|
TEScroll (0, (TEXTREC->viewRect.top - TEXTREC->destRect.top), hTERec);
|
|
|
|
if (TEXTREC->destRect.top < TEXTREC->viewRect.top) { /* make sure we don't get fractions of lineheights */
|
|
int amountOffTheTop = TEXTREC->viewRect.top - TEXTREC->destRect.top;
|
|
if (amountOffTheTop % LINEHEIGHT) TEScroll (0, amountOffTheTop % LINEHEIGHT, hTERec);
|
|
}
|
|
TEUpdate (&(TEXTREC->viewRect), hTERec);
|
|
AdjustScrollBar ();
|
|
UpdateControls (gCommandWin, gCommandWin->visRgn);
|
|
EndUpdate (gCommandWin);
|
|
}
|
|
|
|
void ActivateCmdWindow(void)
|
|
{
|
|
TEActivate (hTERec);
|
|
HiliteControl (vScroll, 0);
|
|
DrawOnlyGrowIcon (gCommandWin);
|
|
}
|
|
|
|
void DeactivateCmdWindow(void)
|
|
{
|
|
TEDeactivate (hTERec);
|
|
HiliteControl (vScroll, 255);
|
|
DrawOnlyGrowIcon (gCommandWin);
|
|
}
|
|
|
|
void InitalizeCmdWindow(void)
|
|
{
|
|
|
|
/* setup the font, size and writing mode for the command window */
|
|
TextFont (kFontIDMonaco);
|
|
TextSize (9);
|
|
TextFace (0);
|
|
TextMode (srcCopy);
|
|
textStyle[plainStyle].tsFace = 0;
|
|
textStyle[boldStyle].tsFace = bold;
|
|
|
|
currentStyle = plainStyle;
|
|
|
|
{ /* set up scroll bar */
|
|
Rect scrollRect;
|
|
vScroll = NewControl (gCommandWin, &scrollRect, "\p", 0, 0, 0, 0, scrollBarProc, 0L);
|
|
SetScrollRect ();
|
|
ShowControl (vScroll);
|
|
}
|
|
|
|
{ /* set up command text record */
|
|
Rect teRect = SetTERect ();
|
|
hTERec = (TEHandle)TEStyleNew (&teRect, &teRect);
|
|
TECalText (hTERec);
|
|
TEAutoView (true, hTERec);
|
|
TESetClickLoop (uppScrollClickLoop, hTERec);
|
|
TEActivate (hTERec);
|
|
}
|
|
|
|
hOutputBuffer = NewHandle (MAX_BUF); /* a handle to a buffer for text to be displayed */
|
|
}
|
|
|
|
void CleanupCmdWindow(void)
|
|
{
|
|
StopPasting ();
|
|
CloseWindow (gCommandWin);
|
|
TEDispose (hTERec);
|
|
DisposeHandle (hOutputBuffer);
|
|
}
|