1 line
99 KiB
C
Executable File
1 line
99 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
||
All rights reserved.
|
||
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
||
the limitations in the disclaimer below) provided that the following conditions are met:
|
||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
||
disclaimer in the documentation and/or other materials provided with the distribution.
|
||
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
||
derived from this software without specific prior written permission.
|
||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
||
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||
DAMAGE. */
|
||
|
||
#include "peteglue.h"
|
||
#include "pete.h"
|
||
#define FILE_NUM 48
|
||
/* Copyright (c) 1995 by Qualcomm, Inc. */
|
||
/* written by Steven Dorner */
|
||
|
||
#pragma segment PGLUE
|
||
|
||
OSErr PeteDragTrack(PETEInst pi,PETEHandle ph,DragTrackingMessage message,DragReference theDragRef);
|
||
Byte PeteLockedAt(PETEHandle pte,long offset);
|
||
OSErr AppendContextSearch(PETEHandle pte,MenuHandle contextMenu);
|
||
|
||
#define ATTRIBUTION_SCRAP_TYPE 'EuAt'
|
||
|
||
/**********************************************************************
|
||
* PeteEdit - wrapper for PETEEdit, that also does URL's and dirty bits
|
||
**********************************************************************/
|
||
OSErr PeteEdit(MyWindowPtr win,PETEHandle ph,PETEEditEnum what,EventRecord* event)
|
||
{
|
||
OSErr err;
|
||
long spot;
|
||
long dirtyWas;
|
||
Point mouse;
|
||
Boolean launch;
|
||
PETEDocInfo info;
|
||
Str255 attribution;
|
||
|
||
if (!ph && win) ph = win->pte;
|
||
|
||
if (!ph) return(fnfErr);
|
||
|
||
if (what==peeEvent && event->what==keyDown)
|
||
{
|
||
if ((*PeteExtra(ph))->not[event->message&charCodeMask])
|
||
return(errAEEventNotHandled);
|
||
}
|
||
|
||
PeteGetTextAndSelection(ph,nil,&spot,nil);
|
||
|
||
// If copying, make an attribution just in case
|
||
if (what==peeCut || what==peeCopy)
|
||
{
|
||
GrabAttribution(ATTR_PASTE_AS_QUOTE,win,attribution);
|
||
if (*attribution) PCatC(attribution,'\015');
|
||
}
|
||
else *attribution = 0;
|
||
|
||
dirtyWas = PeteIsDirty(ph);
|
||
|
||
MightSwitch();
|
||
DragFxxkOff = False;
|
||
err = PETEEdit(PETE,ph,what,event);
|
||
DragFxxkOff = True;
|
||
AfterSwitch();
|
||
if (err) return(err);
|
||
|
||
// stick the attribution on the clipboard
|
||
if (*attribution) PutScrap(*attribution,ATTRIBUTION_SCRAP_TYPE,attribution+1);
|
||
|
||
launch = (win && what==peeEvent && event->what==mouseDown &&
|
||
(ClickType==Double || (event->modifiers & cmdKey)));
|
||
if (launch && ClickType==Double)
|
||
{
|
||
GetMouse(&mouse);
|
||
LocalToGlobal(&mouse);
|
||
if (ABS(mouse.h-event->where.h)>3 || ABS(mouse.v-event->where.v)>3)
|
||
launch = False;
|
||
}
|
||
|
||
if (launch && ClickType==Double)
|
||
{
|
||
PETEGetDocInfo(PETE,ph,&info);
|
||
if (!info.doubleClick) launch = False;
|
||
}
|
||
|
||
if (launch)
|
||
{
|
||
mouse = event->where;
|
||
GlobalToLocal(&mouse);
|
||
if (!PtInPETEView(mouse,ph)) launch = False;
|
||
}
|
||
|
||
if (launch)
|
||
{
|
||
if (!AttIsSelected(win,ph,-1,-1,attAll+(MainEvent.modifiers&controlKey?attFinder:0),nil,nil))
|
||
if (urlNot==URLIsSelected(win,ph,-1,-1,urlOpen|urlSelect,nil,nil))
|
||
if (ClickType==Single) SlackURL(win,ph,-1,-1,urlAll,nil,nil);
|
||
}
|
||
|
||
if (dirtyWas!=PeteIsDirty(ph)) PeteSetURLRescan(ph,spot);
|
||
|
||
PeteSetDirty(ph);
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteKey - handle key
|
||
**********************************************************************/
|
||
OSErr PeteKey(MyWindowPtr win,PETEHandle pte,EventRecord* event)
|
||
{
|
||
OSErr err;
|
||
|
||
if ((*PeteExtra(pte))->numberField)
|
||
{
|
||
// Digits only
|
||
short charCode = event->message&charCodeMask;
|
||
|
||
if ((charCode < '0' || charCode > '9') &&
|
||
DirtyKey(event->message) &&
|
||
charCode != delChar &&
|
||
charCode != backSpace)
|
||
{
|
||
// Not a valid character
|
||
SysBeep(10);
|
||
return errAEEventNotHandled;
|
||
}
|
||
}
|
||
|
||
if (err=PeteEdit(win,pte,peeEvent,event))
|
||
if (err==errAENotModifiable)
|
||
{
|
||
if (PETESelectionLocked(PETE,pte,-1,-1))
|
||
WarnUser(READ_ONLY,err);
|
||
}
|
||
else if (err==errAEEventNotHandled)
|
||
SysBeep(20L);
|
||
else
|
||
WarnUser(PETE_ERR,err);
|
||
|
||
return err;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSelectAll - select "all" in a Pete region
|
||
**********************************************************************/
|
||
void PeteSelectAll(MyWindowPtr win, PETEHandle pte)
|
||
{
|
||
long selStart, selStop;
|
||
PETEStyleEntry pse;
|
||
long offset, lastOffset;
|
||
|
||
// Find the current selection
|
||
PeteGetTextAndSelection(pte,nil,&selStart,&selStop);
|
||
|
||
// Find the end
|
||
|
||
// check for clickBefore
|
||
if (!PeteStyleAt(pte,selStop,&pse) && pse.psStyle.textStyle.tsLock & peClickBeforeLock)
|
||
; // clickBefore; stick with selStop
|
||
else
|
||
{
|
||
// Find the locked text that follows the selection
|
||
pse.psStyle.textStyle.tsLock = peSelectLock;
|
||
if (PETEFindStyle(PETE,pte,selStop,&selStop,&pse.psStyle,peSelectLock<<kPETELockShift))
|
||
selStop = PeteLen(pte); // no locked text; use end of document
|
||
}
|
||
|
||
// Now find the beginning.
|
||
|
||
// check for clickAfter
|
||
if (!PeteStyleAt(pte,selStart-1,&pse) && pse.psStyle.textStyle.tsLock & peClickAfterLock)
|
||
lastOffset = selStart; // clickAfter; stick with selStart
|
||
else
|
||
{
|
||
// This is less fun. Find the last locked text BEFORE the selection
|
||
lastOffset = offset = 0;
|
||
pse.psStyle.textStyle.tsLock = peSelectLock;
|
||
while (!PETEFindStyle(PETE,pte,offset,&offset,&pse.psStyle,peSelectLock<<kPETELockShift))
|
||
{
|
||
// have we gone past?
|
||
if (offset>=selStart) break;
|
||
|
||
// haven't gone past. Now find next UNlocked text
|
||
pse.psStyle.textStyle.tsLock = 0;
|
||
if (PETEFindStyle(PETE,pte,offset,&lastOffset,&pse.psStyle,peSelectLock<<kPETELockShift))
|
||
break; // no unlocked text
|
||
|
||
// look for more locked text
|
||
pse.psStyle.textStyle.tsLock = peSelectLock;
|
||
offset = lastOffset;
|
||
}
|
||
}
|
||
|
||
PeteSelect(win,pte,lastOffset,selStop);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteDidResize - resize a PETE editor thing
|
||
**********************************************************************/
|
||
void PeteDidResize(PETEHandle pte,Rect *view)
|
||
{
|
||
PETEDocInfo info;
|
||
Rect newR;
|
||
Boolean oldFrame;
|
||
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
if (EqualRect(view,&info.docRect)) return;
|
||
|
||
// invalidate old spot
|
||
if (oldFrame = (*PeteExtra(pte))->frame)
|
||
{
|
||
InsetRect(&info.docRect,-2*MAX_APPEAR_RIM,-2*MAX_APPEAR_RIM);
|
||
newR = *view;
|
||
InsetRect(&newR,-2*MAX_APPEAR_RIM,-2*MAX_APPEAR_RIM);
|
||
(*PeteExtra(pte))->frame = false;
|
||
}
|
||
|
||
// move to new spot
|
||
PETEMoveDoc(PETE,pte,view->left,view->top);
|
||
PETESizeDoc(PETE,pte,RectWi(*view),RectHi(*view));
|
||
PETEChangeDocWidth(PETE,pte,(*PeteExtra(pte))->infinitelyWide ? REAL_BIG:-1,True);
|
||
|
||
if ((*PeteExtra(pte))->frame = oldFrame)
|
||
{
|
||
MyWindowPtr win = (*PeteExtra(pte))->win;
|
||
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
||
InvalWindowRect(winWP,&info.docRect);
|
||
InvalWindowRect(winWP,&newR);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteFindString - find a string in a pete
|
||
**********************************************************************/
|
||
long PeteFindString(PStr string,long start,PETEHandle pte)
|
||
{
|
||
long length;
|
||
Handle text;
|
||
|
||
PeteGetRawText(pte,&text);
|
||
length = GetHandleSize(text);
|
||
|
||
if (start + *string > length) return(-1);
|
||
|
||
return(FindStrHandle(string,text,start,nil));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PetePlain - make text plain
|
||
**********************************************************************/
|
||
OSErr PetePlain(PETEHandle pte,long start,long stop,long valid)
|
||
{
|
||
PETEStyleEntry pse;
|
||
|
||
Zero(pse);
|
||
PETEGetStyle(PETE,pte,kPETEDefaultStyle,nil,&pse);
|
||
return(PETESetTextStyle(PETE,pte,start,stop,&pse.psStyle.textStyle,valid));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteNoLabel - unlabel text
|
||
**********************************************************************/
|
||
OSErr PeteNoLabel(PETEHandle pte,long start,long stop,long labelMask)
|
||
{
|
||
return PetePlain(pte,start,stop,labelMask<<kPETELabelShift);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PetePlainParaAt - make some text plain in paragraph attributes
|
||
**********************************************************************/
|
||
OSErr PetePlainParaAtLo(PETEHandle pte,long start,long stop,long valid)
|
||
{
|
||
PETEParaInfo pinfo;
|
||
long fromPara, toPara;
|
||
|
||
Zero(pinfo);
|
||
PETEGetParaInfo(PETE,pte,kPETEDefaultPara,&pinfo);
|
||
PeteEnsureBreak(pte,start);
|
||
PeteEnsureBreak(pte,stop);
|
||
PETEGetParaIndex(PETE,pte,start,&fromPara);
|
||
PETEGetParaIndex(PETE,pte,stop-1,&toPara);
|
||
do
|
||
{
|
||
PETESetParaInfo(PETE,pte,fromPara++,&pinfo,valid);
|
||
} while (fromPara<=toPara);
|
||
return noErr; /* as good an error as any! */
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PetePlainPara - set a particular pargraph to plain
|
||
**********************************************************************/
|
||
OSErr PetePlainParaLo(PETEHandle pte,long index,long valid)
|
||
{
|
||
PETEParaInfo pinfo;
|
||
OSErr err;
|
||
|
||
Zero(pinfo);
|
||
if (!(err=PETEGetParaInfo(PETE,pte,kPETEDefaultPara,&pinfo)))
|
||
err = PETESetParaInfo(PETE,pte,index,&pinfo,valid);
|
||
return(err);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* PeteLink - Link a PTE onto a list
|
||
************************************************************************/
|
||
PETEHandle PeteLink(PETEHandle head,PETEHandle pte)
|
||
{
|
||
PETEHandle tail=head;
|
||
|
||
if (!tail) head = pte;
|
||
else
|
||
{
|
||
while (PeteNext(tail)) tail = PeteNext(tail);
|
||
(*PeteExtra(tail))->next = pte;
|
||
}
|
||
return(head);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PetePrevious - get the previous pte in a list
|
||
**********************************************************************/
|
||
PETEHandle PetePrevious(PETEHandle head,PETEHandle pte)
|
||
{
|
||
if (!PeteIsValid(pte)) return(nil);
|
||
if (pte==head)
|
||
{
|
||
while (PeteNext(pte)) pte=PeteNext(pte);
|
||
return(pte);
|
||
}
|
||
else
|
||
{
|
||
while (head && PeteNext(head)!=pte) head = PeteNext(head);
|
||
return(head);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteApplyResStyle - apply a style from a resource
|
||
**********************************************************************/
|
||
OSErr PeteApplyResStyle(PETEHandle pte,long start,long stop,short styleId)
|
||
{
|
||
PETETextStyle style;
|
||
|
||
GetRColor(&style.tsColor,styleId);
|
||
return PETESetTextStyle(PETE,pte,start,stop,&style,peColorValid);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteRemove - unlink a PETEHandle from a list
|
||
**********************************************************************/
|
||
PETEHandle PeteRemove(PETEHandle head,PETEHandle pte)
|
||
{
|
||
PETEHandle prev, next;
|
||
|
||
if (pte==head)
|
||
head = PeteNext(pte);
|
||
else
|
||
{
|
||
prev = PetePrevious(head,pte);
|
||
if (prev)
|
||
{
|
||
next = PeteNext(pte);
|
||
(*PeteExtra(prev))->next = next;
|
||
}
|
||
}
|
||
|
||
(*PeteExtra(pte))->next = nil;
|
||
return(head);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void PeteFocusPrevious(MyWindowPtr win)
|
||
{
|
||
PeteFocus(win,PetePrevious(win->pteList,win->pte),True);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void PeteFocusNext(MyWindowPtr win)
|
||
{
|
||
PeteFocus(win,PeteNext(win->pte)?PeteNext(win->pte):win->pteList,True);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteCreate - create a pete record, but with extra stuff
|
||
**********************************************************************/
|
||
OSErr PeteCreate(MyWindowPtr win,PETEHandle *ph,uLong flags,PETEDocInitInfoPtr initInfo)
|
||
{
|
||
PeteExtraHandle x = NewZH(PeteExtra);
|
||
OSErr err;
|
||
PETEDocInitInfo info;
|
||
static long id;
|
||
|
||
*ph = nil;
|
||
|
||
if (!x) return(MemError());
|
||
|
||
Zero(info);
|
||
if (!initInfo)
|
||
{
|
||
initInfo = &info;
|
||
DefaultPII(win,False,flags,initInfo);
|
||
}
|
||
|
||
(*x)->win = win;
|
||
(*x)->headers = 0x7fffffff;
|
||
(*x)->id = id++;
|
||
#ifdef WINTERTREE
|
||
if (HasFeature (featureSpellChecking))
|
||
(*x)->spelled = sprNeverSpell; // speller off for most windows
|
||
#endif
|
||
|
||
if (!HaveOSX()) // No offscreen buffering necessary for OS X
|
||
#ifdef DEBUG
|
||
if (!BUG0)
|
||
#endif
|
||
initInfo->docFlags |= peUseOffscreen;
|
||
|
||
#ifdef DEBUG
|
||
if (BUG14) initInfo->docFlags |= peDrawDebugSymbols;
|
||
#endif
|
||
|
||
err = PETECreate(PETE,ph,initInfo);
|
||
|
||
if (err)
|
||
{
|
||
ZapHandle(x);
|
||
*ph = nil; // just making sure
|
||
}
|
||
else
|
||
{
|
||
PETESetRefCon(PETE,*ph,(long)x);
|
||
win->pteList = PeteLink(win->pteList,*ph);
|
||
PETESetCallback(PETE,*ph,(void*)PeteBusy,peProgressLoop);
|
||
}
|
||
|
||
CleanPII(&info);
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void CleanPII(PETEDocInitInfoPtr pii)
|
||
{
|
||
ZapHandle(pii->inParaInfo.tabHandle);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void PeteDispose(MyWindowPtr win,PETEHandle ph)
|
||
{
|
||
long extra = PETEGetRefCon(PETE,ph);
|
||
StackHandle stack = (*(PeteExtraHandle)extra)->partStack;
|
||
|
||
if (!ph) return;
|
||
if (win->pte==ph) PeteFocus(win,nil,True);
|
||
if (win) win->pteList = PeteRemove(win->pteList,ph);
|
||
ZapHandle ((*(PeteExtraHandle)extra)->nick.addresses);
|
||
PETEDispose(PETE,ph);
|
||
if (stack) ZapHandle(stack);
|
||
DisposeHandle((void*)extra);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* MPETEAppendText - append some text to a te region
|
||
**********************************************************************/
|
||
OSErr PeteAppendText(UPtr text,long size,PETEHandle pte)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
err = PETEInsertTextPtr(PETE,pte,0x7fffffff,text,size,nil);
|
||
return err;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteFocus - focus a window on a PTE
|
||
**********************************************************************/
|
||
void PeteFocus(MyWindowPtr win,PETEHandle pte, Boolean focus)
|
||
{
|
||
Boolean activeState = !InBG && focus && (win->isActive || IsFloating(GetMyWindowWindowPtr(win)));
|
||
|
||
if (pte && HasNickScanCapability (pte))
|
||
NicknameWatcherFocusChange (pte);
|
||
|
||
if (focus)
|
||
{
|
||
if (win->pte && pte!=win->pte)
|
||
{
|
||
if ((*PeteExtra(win->pte))->frame)
|
||
PeteHotRect(win->pte,False);
|
||
PeteActivate(win->pte,False,True);
|
||
}
|
||
win->pte = pte;
|
||
if (IsFloating(GetMyWindowWindowPtr(win))) SetKeyFocusedFloater(pte?win:nil);
|
||
}
|
||
if (pte)
|
||
{
|
||
if ((*PeteExtra(pte))->frame)
|
||
PeteHotRect(pte,activeState);
|
||
PeteActivate(pte,activeState,true);
|
||
}
|
||
win->hasSelection = MyWinHasSelection(win);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteActivateLo - activate a PETE handle, but allow one to be locked
|
||
**********************************************************************/
|
||
void PeteActivateLo(PETEHandle pte, Boolean doc, Boolean scroll,Boolean lock)
|
||
{
|
||
static PETEHandle lockedPTE;
|
||
|
||
if (lock)
|
||
{
|
||
lockedPTE = pte;
|
||
// manage the activation of the non-floater pte, if any
|
||
{
|
||
WindowPtr winWP = MyFrontNonFloatingWindow();
|
||
if (winWP)
|
||
{
|
||
MyWindowPtr win = GetWindowMyWindowPtr(winWP);
|
||
if (win && win->pte && win->pte != pte)
|
||
PETEActivate(PETE,win->pte,pte==nil,true);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (lockedPTE && pte!=lockedPTE) doc = false;
|
||
PETEActivate(PETE,pte,doc,scroll);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteDrag(MyWindowPtr win,DragTrackingMessage message,DragReference drag)
|
||
{
|
||
OSErr dragErr;
|
||
static PETEHandle oldPTE;
|
||
Point mouse;
|
||
PETEHandle pte;
|
||
|
||
PushGWorld();
|
||
|
||
if (win)
|
||
{
|
||
SetPort_(GetMyWindowCGrafPtr(win));
|
||
GetDragMouse(drag,&mouse,nil);
|
||
GlobalToLocal(&mouse);
|
||
PopGWorld();
|
||
for (pte=win->pteList;pte;pte=PeteNext(pte))
|
||
if (PtInPETE(mouse,pte)) break;
|
||
}
|
||
else
|
||
{
|
||
PopGWorld();
|
||
pte = nil;
|
||
}
|
||
|
||
if (oldPTE!=pte)
|
||
{
|
||
//Dprintf("\p%x %x;g",pte,oldPTE);
|
||
if (PeteIsValid(oldPTE))// && message!=kDragTrackingLeaveWindow)
|
||
PeteDragTrack(PETE,oldPTE,kDragTrackingLeaveWindow,drag);
|
||
if (pte && message!=kDragTrackingEnterWindow)
|
||
PeteDragTrack(PETE,pte,kDragTrackingEnterWindow,drag);
|
||
oldPTE = pte;
|
||
}
|
||
|
||
if (pte)
|
||
{
|
||
if (message == 0xfff)
|
||
/* MJN *//* formatting toolbar */
|
||
/* return(PETEDragReceiveHandler(PETE,pte,drag)); */
|
||
{
|
||
|
||
// preprocess
|
||
if ((*PeteExtra(pte))->dragPreProcess)
|
||
(*PeteExtra(pte))->dragPreProcess(pte,message,drag);
|
||
|
||
dragErr = PETEDragReceiveHandler(PETE,pte,drag);
|
||
|
||
// postprocess
|
||
if ((*PeteExtra(pte))->dragPostProcess)
|
||
(*PeteExtra(pte))->dragPostProcess(pte,message,drag);
|
||
|
||
RequestTFBEnableCheck(win);
|
||
return(dragErr);
|
||
}
|
||
else
|
||
{
|
||
#ifdef NEVER
|
||
if (message==dragTrackingLeaveWindow) oldPTE = nil; //we're leaving, see that we don't
|
||
//leave twice
|
||
#endif
|
||
return(PeteDragTrack(PETE,pte,message,drag));
|
||
}
|
||
}
|
||
return(dragNotAcceptedErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteDragTrack(PETEInst pi,PETEHandle ph,DragTrackingMessage message,DragReference theDragRef)
|
||
{
|
||
OSErr err;
|
||
#ifdef NEVER
|
||
ComposeLogS(-1,nil,"\p%x %x",message,ph);
|
||
#endif
|
||
|
||
// preprocess
|
||
if ((*PeteExtra(ph))->dragPreProcess)
|
||
(*PeteExtra(ph))->dragPreProcess(ph,message,theDragRef);
|
||
|
||
// process
|
||
err = PETEDragTrackingHandler(pi,ph,message,theDragRef);
|
||
|
||
// postprocess
|
||
if ((*PeteExtra(ph))->dragPostProcess)
|
||
(*PeteExtra(ph))->dragPostProcess(ph,message,theDragRef);
|
||
|
||
return err;
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteWrap(MyWindowPtr win, PETEHandle pte, Boolean unwrap)
|
||
{
|
||
Handle text;
|
||
OSErr err;
|
||
long start,stop;
|
||
long len;
|
||
|
||
PeteCalcOff(pte);
|
||
start = stop = -1;
|
||
PeteParaRange(pte,&start,&stop);
|
||
PeteParaConvert(pte,start,stop);
|
||
PeteSelect(win,pte,start,stop);
|
||
PetePrepareUndo(pte,peUndoPaste,-1,-1,nil,nil);
|
||
|
||
if (!unwrap)
|
||
{
|
||
ConvertExcerpt(pte,start,stop,&start,&stop);
|
||
PeteSelect(win,pte,start,stop);
|
||
}
|
||
|
||
if (err=PeteGetTextAndSelection(pte,&text,nil,nil)) return(err);
|
||
|
||
if (!(err=TextWrap(text,start,stop,unwrap)))
|
||
{
|
||
len = GetHandleSize(WrapHandle);
|
||
|
||
// make sure last char is CR
|
||
if (unwrap && (!len || (*WrapHandle)[len-1]!='\015'))
|
||
{
|
||
SetHandleBig(WrapHandle,len+1);
|
||
if (!MemError()) (*WrapHandle)[len++] = '\015';
|
||
}
|
||
|
||
stop = len+start;
|
||
|
||
err = PETEInsertText(PETE,pte,-1,WrapHandle,nil);
|
||
|
||
if (err)
|
||
{
|
||
ZapHandle(WrapHandle);
|
||
PeteKillUndo(pte);
|
||
}
|
||
else
|
||
{
|
||
WrapHandle = nil;
|
||
PetePlain(pte,start,stop,peAllValid);
|
||
PetePlainParaAtLo(pte,start,stop,peAllParaValidButTabs);
|
||
PeteFinishUndo(pte,peUndoPaste,start,stop);
|
||
PeteSelect(win,pte,start,stop);
|
||
}
|
||
PeteSetDirty(pte);
|
||
}
|
||
else PeteKillUndo(pte);
|
||
|
||
if (err) WarnUser(PETE_ERR,err);
|
||
PeteCalcOn(pte);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PETESetDirty - set the dirty bit for a window, and return whether or not
|
||
* an peteedit thing is dirty.
|
||
**********************************************************************/
|
||
Boolean PeteSetDirty(PETEHandle pte)
|
||
{
|
||
PETEDocInfo info;
|
||
MyWindowPtr win;
|
||
|
||
if (PeteIsValid(pte))
|
||
{
|
||
win = (*PeteExtra(pte))->win;
|
||
if (PETEGetDocInfo(PETE,pte,&info)) return(False);
|
||
win->isDirty = win->isDirty || info.dirty;
|
||
if (win->pte == pte) win->hasSelection = info.selStop!=info.selStart;
|
||
return(info.dirty);
|
||
}
|
||
return(False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteSetURLRescan(PETEHandle pte,long spot)
|
||
{
|
||
PETEParaInfo pInfo;
|
||
|
||
if (NoScannerResets) return(noErr);
|
||
spot = MAX(0,spot-256);
|
||
|
||
#define SET_SCANNER(scanner,spot) do {if (scanner<0 || scanner>spot) scanner = spot;}while(0)
|
||
|
||
// the URL scanner
|
||
SET_SCANNER((*PeteExtra(pte))->urlScanned,spot);
|
||
|
||
// emoticons
|
||
SET_SCANNER((*PeteExtra(pte))->emoScanned,spot);
|
||
|
||
// the speller
|
||
#ifdef WINTERTREE
|
||
if (HasFeature (featureSpellChecking) && !SpellDisabled(pte))
|
||
{
|
||
SET_SCANNER((*PeteExtra(pte))->spelled,spot);
|
||
(*PeteExtra(pte))->spellReset = true;
|
||
}
|
||
#endif
|
||
|
||
// for quote scanner, be sure to go back to start of last para
|
||
Zero(pInfo);
|
||
PETEGetParaInfo(PETE,pte,PeteParaAt(pte,spot),&pInfo);
|
||
spot = MIN(spot,pInfo.paraOffset?pInfo.paraOffset-1:0);
|
||
SET_SCANNER((*PeteExtra(pte))->quoteScanned,spot);
|
||
|
||
// ouch; for tae, back all the way out
|
||
(*PeteExtra(pte))->taeScanned = 0;
|
||
return noErr; /* ??? */
|
||
}
|
||
|
||
|
||
//
|
||
// PeteNickScan
|
||
//
|
||
// Performs nickname scanning operations
|
||
//
|
||
|
||
void PeteNickScan (PETEHandle pte)
|
||
|
||
{
|
||
if ((*PeteExtra(pte))->nick.fieldCheck ? (*(*PeteExtra(pte))->nick.fieldCheck) (pte) : HasNickScanCapability (pte))
|
||
NicknameHilitingUpdateField (pte);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* HorizRuleGraphic - Callback to handle a graphic that is an horizontal rule
|
||
**********************************************************************/
|
||
pascal OSErr HorizRuleGraphic(PETEHandle pte,PETEGraphicInfoHandle graphic,long offset,PETEGraphicMessage message,void *data)
|
||
{
|
||
OSErr err = noErr;
|
||
Rect r;
|
||
Rect rule;
|
||
HRGraphicHandle hrg = (void*)graphic;
|
||
short wi;
|
||
|
||
switch (message)
|
||
{
|
||
case peGraphicDraw: /* data is (Point *) with penLoc at baseline left as a point */
|
||
PeteGraphicRect(&r,pte,graphic,offset);
|
||
SetRect(&rule,0,0,RectWi(r),(*hrg)->hi?(*hrg)->hi:2);
|
||
CenterRectIn(&rule,&r);
|
||
if ((*hrg)->groovy && !HaveTheDiseaseCalledOSX()) DrawThemeSeparator(&rule,kThemeStateActive);
|
||
else
|
||
{
|
||
PenNormal();
|
||
SET_COLORS;
|
||
if ((*hrg)->groovy && HaveTheDiseaseCalledOSX()) SetForeGrey(GetRLong(SEP_LINE_GREY));
|
||
PaintRect(&rule);
|
||
}
|
||
break;
|
||
|
||
case peGraphicClone: /* data is (PETEGraphicInfoHandle *) into which to put duplicate */
|
||
*(PETEGraphicInfoHandle*)data = (PETEGraphicInfoHandle) DupHandle((Handle)graphic);
|
||
err = MemError();
|
||
break;
|
||
|
||
case peGraphicTest: /* data is (Point *) from top left; return errOffsetIsOutsideOfView if not hit */
|
||
// Can cancel hit by returning errOffsetIsOutsideOfView
|
||
break;
|
||
|
||
case peGraphicHit: /* data is (EventRecord *) if mouse down, nil if time to turn off */
|
||
break;
|
||
|
||
case peGraphicRemove: /* data is nil; just dispose a copy of graphic */
|
||
DisposeHandle((Handle)graphic);
|
||
break;
|
||
|
||
case peGraphicResize: /* data is a (short *) of the max width */
|
||
wi = *(short*)data;
|
||
if ((*hrg)->wi>0) wi = MIN((*hrg)->wi,wi);
|
||
else if ((*hrg)->wi<0) wi = -(wi*(*hrg)->wi)/100;
|
||
(*hrg)->gi.width = wi;
|
||
(*hrg)->gi.height = (*hrg)->hi ? (*hrg)->hi : FontLead;
|
||
break;
|
||
|
||
case peGraphicRegion: /* data is a RgnHandle which is to be changed to the graphic's region */
|
||
// Used mostly for changing the cursor
|
||
PeteGraphicRect(&r,pte,graphic,offset);
|
||
RectRgn((RgnHandle)data,&r);
|
||
break;
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* PeteInsertRule - insert a horizontal rule
|
||
************************************************************************/
|
||
OSErr PeteInsertRule(PETEHandle pte,long offset,short width,short height,Boolean groovy,Boolean withParas,Boolean undo)
|
||
{
|
||
PETEStyleEntry pse;
|
||
OSErr err;
|
||
HRGraphicHandle graphic = NewZH(HorizRuleGraphicInfo);
|
||
PETEParaInfo pinfo;
|
||
Boolean did;
|
||
|
||
if (!graphic) return(MemError());
|
||
|
||
PeteStyleAt(pte,offset,&pse);
|
||
Zero(pinfo);
|
||
PETEGetParaInfo(PETE,pte,PeteParaAt(pte,offset),&pinfo);
|
||
|
||
/*
|
||
* figure out how long the paragraph is
|
||
*/
|
||
pinfo.tabHandle = nil;
|
||
pse.psStartChar = 0;
|
||
pse.psGraphic = 1;
|
||
pse.psStyle.graphicStyle.graphicInfo = (void*)graphic;
|
||
(*graphic)->gi.width = pinfo.endMargin - pinfo.startMargin - pinfo.indent;
|
||
(*graphic)->gi.height = FontLead;
|
||
(*graphic)->gi.descent = FontDescent;
|
||
(*graphic)->gi.itemProc = HorizRuleGraphic;
|
||
(*graphic)->gi.privateType = pgtHorizontalRule;
|
||
(*graphic)->wi = width;
|
||
(*graphic)->hi = height;
|
||
(*graphic)->groovy = groovy;
|
||
pse.psStyle.textStyle.tsLock = 0;
|
||
**Pslh = pse;
|
||
if(undo) PetePrepareUndo(pte,peUndoPaste,-1,-1,nil,nil);
|
||
err = PeteInsertChar(pte,offset,'\015',Pslh); ASSERT(!err);
|
||
if (!err && withParas)
|
||
{
|
||
PeteGetTextAndSelection(pte,nil,&offset,nil);
|
||
PeteEnsureBreak(pte,offset);
|
||
PeteEnsureCrAndBreakLo(pte,offset-1,nil,&did);
|
||
PeteEnsureTrailingEmpty(pte);
|
||
if(undo) PeteFinishUndo(pte,peUndoPaste,did?offset-2:offset-1,offset);
|
||
}
|
||
else if(undo) PeteKillUndo(pte);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteInsert - insert handle, using the style at the offset in question
|
||
**********************************************************************/
|
||
OSErr PeteInsert(PETEHandle pte,long offset,Handle text)
|
||
{
|
||
OSErr err;
|
||
PETEStyleEntry pse;
|
||
PETEDocInfo info;
|
||
long styleOffset = offset;
|
||
|
||
if (styleOffset==-1)
|
||
{
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
if (info.selStart!=info.selStop)
|
||
styleOffset = info.selStart;
|
||
else
|
||
styleOffset = MAX(0,info.selStart-1);
|
||
}
|
||
PeteStyleAt(pte,styleOffset,&pse);
|
||
pse.psStyle.textStyle.tsLock = pse.psStartChar = 0;
|
||
**Pslh = pse;
|
||
err = PETEInsertTextPtr(PETE,pte,offset,LDRef(text),GetHandleSize(text),Pslh);
|
||
UL(text);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PetePasteQ - paste as quote
|
||
**********************************************************************/
|
||
OSErr PetePasteQ(MyWindowPtr win,Boolean plain)
|
||
{
|
||
long start, stop, undoStart, undoStop, newStop, finalInsertion;
|
||
OSErr err;
|
||
Boolean rich;
|
||
Str63 quoth;
|
||
Handle textH;
|
||
long dirtySpot;
|
||
Handle scrapH;
|
||
long junk;
|
||
long len;
|
||
|
||
// Grab the current selection and keep track of it for undo
|
||
PetePrepareUndo(win->pte,peUndoPaste,-1,-1,&start,&stop);
|
||
undoStop = stop;
|
||
undoStart = start;
|
||
dirtySpot = start;
|
||
|
||
// Paste as quote always goes on own line. Check to see if we need to insert a return before
|
||
PeteGetTextAndSelection(win->pte,&textH,nil,nil);
|
||
if (start && (*textH)[start-1]!='\015')
|
||
{
|
||
PeteInsertChar(win->pte,-1,'\015',nil);
|
||
if (start+1==PETEGetTextLen(PETE,win->pte))
|
||
PeteInsertPlainParaAtEnd(win->pte);
|
||
else
|
||
PeteEnsureBreak(win->pte,start+1);
|
||
undoStop++;
|
||
start++;
|
||
stop++;
|
||
//PETESelect(PETE,win->pte,start,stop); // The cr goes in after the start of the selection, so we
|
||
// need to move the selection
|
||
}
|
||
|
||
// Do we have a stored attribution? If so, insert now
|
||
if (scrapH=NuHandle(0))
|
||
{
|
||
if ((len=GetScrap(scrapH,ATTRIBUTION_SCRAP_TYPE,&junk))>0)
|
||
{
|
||
PeteInsert(win->pte,-1,scrapH);
|
||
undoStop += len;
|
||
start += len;
|
||
stop += len;
|
||
//PETESelect(PETE,win->pte,start,stop); // The cr goes in after the start of the selection, so we
|
||
// need to move the selection
|
||
}
|
||
}
|
||
|
||
// Do the paste
|
||
err = PeteEdit(win,win->pte,plain?peePastePlain:peePaste,&MainEvent);
|
||
if (!err)
|
||
{
|
||
PeteEnsureBreak(win->pte,start); // make sure we get a para break in any case
|
||
|
||
// Ok, where does the pasted section end?
|
||
PeteGetTextAndSelection(win->pte,&textH,nil,&stop);
|
||
finalInsertion = undoStop = stop;
|
||
|
||
// If the insertion point isn't at a line start, insert a return before it
|
||
if (stop && (*textH)[stop-1]!='\015')
|
||
{
|
||
PeteInsertChar(win->pte,stop,'\015',nil);
|
||
PeteEnsureBreak(win->pte,stop+1);
|
||
undoStop++;
|
||
stop++;
|
||
finalInsertion++;
|
||
}
|
||
|
||
// If the insertion point is at the end of the doc, insert para
|
||
if (stop==PETEGetTextLen(PETE,win->pte))
|
||
PeteInsertPlainParaAtEnd(win->pte);
|
||
//If the insertion point is not at the end of a line, insert return & para
|
||
else if ((*textH)[stop]!='\015')
|
||
{
|
||
PeteInsertChar(win->pte,stop,'\015',nil);
|
||
PeteEnsureBreak(win->pte,stop+1);
|
||
undoStop++;
|
||
}
|
||
|
||
// Figure out if rich text was involved
|
||
if (IsMessWindow(GetMyWindowWindowPtr(win)))
|
||
{
|
||
if (UseFlowOutExcerpt && !MessFlagIsSet(Win2MessH(win),FLAG_SHOW_ALL))
|
||
rich = true;
|
||
else
|
||
{
|
||
SetMessRich(Win2MessH(win));
|
||
rich = MessIsRich(Win2MessH(win));
|
||
}
|
||
}
|
||
else rich = HasStyles(win->pte,0,PETEGetTextLen(PETE,win->pte),false);
|
||
|
||
//
|
||
// Now, either excerpt or insert quote characters
|
||
//
|
||
if (rich)
|
||
{
|
||
PetePlain(win->pte,kPETECurrentStyle,kPETECurrentStyle,peAllValid);
|
||
if (*GetRString(quoth,QUOTH))
|
||
{
|
||
PCatC(quoth,'\015');
|
||
PeteInsertPtr(win->pte,start,quoth+1,*quoth);
|
||
PeteEnsureBreak(win->pte,start);
|
||
PeteEnsureBreak(win->pte,start+*quoth);
|
||
PetePlain(win->pte,start,start+*quoth,peAllValid);
|
||
PetePlainParaAtLo(win->pte,start,start+*quoth,peAllParaValid&~(peTabsValid|peQuoteLevelValid));
|
||
start += *quoth;
|
||
stop += *quoth;
|
||
undoStop += *quoth;
|
||
finalInsertion += *quoth;
|
||
}
|
||
if (*GetRString(quoth,UNQUOTH))
|
||
{
|
||
PCatC(quoth,'\015');
|
||
PeteInsertPtr(win->pte,stop,quoth+1,*quoth);
|
||
PeteEnsureBreak(win->pte,stop);
|
||
PeteEnsureBreak(win->pte,stop+*quoth);
|
||
undoStop += *quoth;
|
||
finalInsertion += *quoth;
|
||
PetePlain(win->pte,stop,stop+*quoth+1,peAllValid);
|
||
PetePlainParaAtLo(win->pte,stop,stop+*quoth,peAllParaValid&~(peTabsValid|peQuoteLevelValid));
|
||
}
|
||
PeteExcerpt(win->pte,start,stop-1);
|
||
#ifdef NEVER
|
||
//convert the excerpts to plain quotes
|
||
ConvertExcerpt(win->pte,start,stop,&newStop);
|
||
undoStop += newStop-stop;
|
||
finalInsertion += newStop-stop;
|
||
//and quote the entire selection with ">"s
|
||
QuoteLines(win->pte,start-1,stop,QUOTE_PREFIX,&newStop);
|
||
undoStop += newStop-stop;
|
||
finalInsertion += newStop-stop;
|
||
#endif //NEVER
|
||
}
|
||
else
|
||
{
|
||
QuoteLines(win->pte,start-1,stop,QUOTE_PREFIX,&newStop);
|
||
undoStop += newStop-stop;
|
||
finalInsertion += newStop-stop;
|
||
}
|
||
PETESelect(PETE,win->pte,finalInsertion,finalInsertion);
|
||
PetePlainParaAt(win->pte,finalInsertion,finalInsertion);
|
||
PeteLock(win->pte,kPETECurrentStyle,kPETECurrentStyle,0); // just in case lock leaked in
|
||
PeteFinishUndo(win->pte,peUndoPaste,undoStart,undoStop);
|
||
}
|
||
else PeteKillUndo(win->pte);
|
||
|
||
PeteSetURLRescan(win->pte,dirtySpot);
|
||
PeteNickScan (win->pte);
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteInsertPlainParaAtEnd - Insert a plain para at the end of the doc
|
||
**********************************************************************/
|
||
OSErr PeteInsertPlainParaAtEnd(PETEHandle pte)
|
||
{
|
||
PETEParaInfo pinfo;
|
||
OSErr err;
|
||
Zero(pinfo);
|
||
|
||
if (!(err=PETEGetParaInfo(PETE,pte,kPETEDefaultPara,&pinfo)))
|
||
if (pinfo.tabHandle=NuHandle(sizeof(**(pinfo.tabHandle))))
|
||
{
|
||
pinfo.tabCount = kPETEFixedTab;
|
||
**pinfo.tabHandle = GetRLong(TAB_DISTANCE)*FontWidth;
|
||
err = PETEInsertParaPtr(PETE,pte,kPETELastPara,&pinfo,nil,0,nil);
|
||
ZapHandle(pinfo.tabHandle);
|
||
}
|
||
else err = MemError();
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* MouseInPTE - is the mouse in a PETE record?
|
||
**********************************************************************/
|
||
Boolean MouseInPTE(PETEHandle pte)
|
||
{
|
||
Point pt;
|
||
GetMouse(&pt);
|
||
return(PtInPETE(pt,pte));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteUndoType - return the undo state
|
||
**********************************************************************/
|
||
PETEUndoEnum PeteUndoType(PETEHandle pte)
|
||
{
|
||
PETEDocInfo info;
|
||
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
return(info.undoType);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteInsertPtr - insert pointer, using the style at the offset in question
|
||
**********************************************************************/
|
||
OSErr PeteInsertPtr(PETEHandle pte,long offset,Ptr text,long size)
|
||
{
|
||
OSErr err;
|
||
PETEStyleEntry pse;
|
||
|
||
PeteStyleAt(pte,offset,&pse);
|
||
pse.psStyle.textStyle.tsLock = 0;
|
||
pse.psStartChar = 0;
|
||
**Pslh = pse;
|
||
err = PETEInsertTextPtr(PETE,pte,offset,text,size,Pslh);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteInsertChar - insert a single character
|
||
**********************************************************************/
|
||
OSErr PeteInsertChar(PETEHandle pte,long offset,unsigned char insertChar,PETEStyleListHandle styles)
|
||
{
|
||
return PETEInsertTextPtr(PETE,pte,offset,&insertChar,1,styles);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteGraphicRect - return the rectangle of a graphic
|
||
**********************************************************************/
|
||
OSErr PeteGraphicRect(Rect *r,PETEHandle pte,PETEGraphicInfoHandle graphic,long offset)
|
||
{
|
||
Point p;
|
||
LHElement lineHeight;
|
||
OSErr err;
|
||
|
||
err = PETEOffsetToPosition(PETE,pte,offset,&p,&lineHeight);
|
||
p.v += lineHeight.lhAscent+(*graphic)->descent;
|
||
SetRect(r,p.h,p.v-(*graphic)->height,p.h+(*graphic)->width,p.v);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteHide - hide some text by putting a nil graphic over it
|
||
**********************************************************************/
|
||
OSErr PeteHide(PETEHandle pte,long start,long stop)
|
||
{
|
||
PETEStyleEntry pse;
|
||
long junk;
|
||
OSErr err=noErr;
|
||
Handle text;
|
||
Str255 old;
|
||
Boolean dirty = PeteIsDirty(pte);
|
||
Boolean winDirty = (*PeteExtra(pte))->win->isDirty;
|
||
PETEStyleListHandle pslh;
|
||
|
||
Zero(pse);
|
||
PETEGetStyle(PETE,pte,start,&junk,&pse);
|
||
if (!pse.psGraphic)
|
||
{
|
||
Zero(pse);
|
||
pse.psGraphic = true;
|
||
PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
MakePStr(old,*text+start,stop-start);
|
||
PeteDelete(pte,start,stop);
|
||
if (pslh = NewZH(PETEStyleEntry))
|
||
{
|
||
**pslh = pse;
|
||
err = PETEInsertTextPtr(PETE,pte,start,old+1,*old,pslh);
|
||
ZapHandle(pslh);
|
||
}
|
||
PETEMarkDocDirty(PETE,pte,dirty);
|
||
(*PeteExtra(pte))->win->isDirty = winDirty;
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteClearGraphic - clear graphic from a selection
|
||
**********************************************************************/
|
||
OSErr PeteClearGraphic(PETEHandle pte,long start,long stop)
|
||
{
|
||
PETEStyleInfo psi;
|
||
OSErr err;
|
||
|
||
Zero(psi);
|
||
|
||
err = PETESetStyle(PETE,pte,start,stop,&psi,peColorValid|peGraphicColorChangeValid);
|
||
return err;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteLabel - label some text
|
||
**********************************************************************/
|
||
OSErr PeteLabel(PETEHandle pte,long selStart,long selEnd,short label,long labelMask)
|
||
{
|
||
PETETextStyle pStyle;
|
||
|
||
Zero(pStyle);
|
||
pStyle.tsLabel = label;
|
||
return(PETESetTextStyle(PETE,pte,selStart,selEnd,&pStyle,labelMask<<kPETELabelShift));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteStyleAt - what's the style at a point?
|
||
**********************************************************************/
|
||
OSErr PeteStyleAt(PETEHandle pte,long offset,PETEStyleEntryPtr theStyle)
|
||
{
|
||
PETEDocInfo info;
|
||
OSErr err;
|
||
|
||
if (offset==-1)
|
||
{
|
||
if (err = PETEGetDocInfo(PETE,pte,&info)) return err;
|
||
if (info.selStart!=info.selStop)
|
||
offset = info.selStart;
|
||
else
|
||
offset = MAX(0,info.selStart-1);
|
||
}
|
||
err = PeteGetStyle(pte,offset,nil,theStyle);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteLockedAt - how locked is something?
|
||
**********************************************************************/
|
||
Byte PeteLockedAt(PETEHandle pte,long offset)
|
||
{
|
||
PETEStyleEntry pse;
|
||
Zero(pse);
|
||
PeteStyleAt(pte,offset,&pse);
|
||
return(pse.psStyle.textStyle.tsLock);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteIsGraphicAt - how locked is something?
|
||
**********************************************************************/
|
||
Boolean PeteIsGraphicAt(PETEHandle pte,long offset)
|
||
{
|
||
PETEStyleEntry pse;
|
||
Zero(pse);
|
||
PeteStyleAt(pte,offset,&pse);
|
||
return(pse.psGraphic);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteGetStyleLo(PETEHandle pte,long offset,long *runLen,Boolean allowGraphic,PETEStyleEntryPtr theStyle)
|
||
{
|
||
OSErr err = PETEGetStyle(PETE,pte,offset,runLen,theStyle);
|
||
if (!allowGraphic) PeteJustSayNoGraphic(theStyle);
|
||
if (!runLen) theStyle->psStartChar = 0;
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void PeteJustSayNoGraphic(PETEStyleEntryPtr theStyle)
|
||
{
|
||
if (theStyle->psGraphic && theStyle->psStyle.graphicStyle.graphicInfo)
|
||
{
|
||
theStyle->psGraphic = 0;
|
||
DEFAULT_COLOR(theStyle->psStyle.textStyle.tsColor);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PtInPTE - is a point in a PTE
|
||
**********************************************************************/
|
||
Boolean PtInPETE(Point pt,PETEHandle pte)
|
||
{
|
||
PETEDocInfo pinfo;
|
||
|
||
PETEGetDocInfo(PETE,pte,&pinfo);
|
||
return(PtInRect(pt,&pinfo.docRect));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PtInPTEView - is a point in a PTE's view rectangle
|
||
**********************************************************************/
|
||
Boolean PtInPETEView(Point pt,PETEHandle pte)
|
||
{
|
||
PETEDocInfo pinfo;
|
||
|
||
PETEGetDocInfo(PETE,pte,&pinfo);
|
||
return(PtInRect(pt,&pinfo.viewRect));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteCursorList - set cursor according to list of pte's
|
||
**********************************************************************/
|
||
Boolean PeteCursorList(PETEHandle pte,Point mouse)
|
||
{
|
||
EventRecord event;
|
||
|
||
for (;pte;pte=PeteNext(pte))
|
||
{
|
||
if (PtInPETE(mouse,pte))
|
||
{
|
||
OSEventAvail(nil,&event);
|
||
PETECursor(PETE,pte,mouse,nil,&event);
|
||
return(True);
|
||
}
|
||
}
|
||
return(False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSelectWord - expand the insertion point to the current word
|
||
**********************************************************************/
|
||
OSErr PeteSelectWord(MyWindowPtr win,PETEHandle pte,long offset)
|
||
{
|
||
OSErr err = noErr;
|
||
#ifdef WINTERTREE
|
||
PETEStyleEntry pse;
|
||
#endif //WINTERTREE
|
||
long selStart,selEnd;
|
||
|
||
if (offset==-1) PeteGetTextAndSelection(pte,nil,&offset,nil);
|
||
|
||
#ifdef WINTERTREE
|
||
if (HasFeature (featureSpellChecking)) {
|
||
PeteStyleAt(pte,offset,&pse);
|
||
if ((pse.psStyle.textStyle.tsLabel&(pURLLabel|pSpellLabel)) != 0)
|
||
err = PETEFindLabelRun(PETE,pte,MAX(0,offset-1),&selStart,&selEnd,pse.psStyle.textStyle.tsLabel&(pURLLabel|pSpellLabel),pse.psStyle.textStyle.tsLabel&(pURLLabel|pSpellLabel));
|
||
else
|
||
err = PETEGetWord(PETE,pte,offset,true,&selStart,&selEnd,nil,nil);
|
||
}
|
||
else
|
||
err = PETEGetWord(PETE,pte,offset,true,&selStart,&selEnd,nil,nil);
|
||
#else
|
||
err = PETEGetWord(PETE,pte,offset,true,&selStart,&selEnd,nil,nil);
|
||
#endif //WINTERTREE
|
||
PeteSelect(win,pte,selStart,selEnd);
|
||
return err;
|
||
}
|
||
|
||
/************************************************************************
|
||
* AppendEditItems - add pete items
|
||
************************************************************************/
|
||
OSErr AppendEditItems(MyWindowPtr win,EventRecord *event,MenuHandle contextMenu)
|
||
{
|
||
Point pt = event->where;
|
||
long offset;
|
||
long start, stop;
|
||
PETEHandle pte;
|
||
|
||
// are we over a PETE region?
|
||
GlobalToLocal(&pt);
|
||
|
||
ASSERT(win);
|
||
if (!win) return fnfErr;
|
||
|
||
for (pte=win->pteList;pte;pte=(*PeteExtra(pte))->next)
|
||
if (PtInPETE(pt,pte)) break;
|
||
if (!pte) return(noErr);
|
||
|
||
// call the context menus
|
||
if (!PETEPositionToOffset(PETE,pte,pt,&offset) && !(PeteLockedAt(pte,offset)&peSelectLock))
|
||
{
|
||
PeteGetTextAndSelection(pte,nil,&start,&stop);
|
||
if (offset<start || offset>stop)
|
||
if (RequestPeteFocus(win,pte))
|
||
{
|
||
if (AttIsSelected(nil,pte,offset,offset,0,nil,nil))
|
||
{
|
||
;
|
||
}
|
||
else
|
||
{
|
||
PeteSelect((*PeteExtra(pte))->win,pte,offset,offset);
|
||
PeteSelectWord((*PeteExtra(pte))->win,pte,offset);
|
||
}
|
||
SetMenuTexts(event->modifiers,false);
|
||
}
|
||
#ifdef WINTERTREE
|
||
if (HasFeature (featureSpellChecking) && !SpellDisabled(pte) && HaveSpeller()) AppendSpellItems(pte,contextMenu);
|
||
#endif
|
||
#ifdef CONTEXT_FILING
|
||
if (HasFeature(featureContextualFiling)) AppendXferSelection(pte,contextMenu);
|
||
#endif
|
||
#ifdef CONTEXT_SEARCH
|
||
AppendContextSearch(pte,contextMenu);
|
||
#endif
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
#ifdef CONTEXT_SEARCH
|
||
/************************************************************************
|
||
* AppendContextSearch - append contextual search items
|
||
************************************************************************/
|
||
OSErr AppendContextSearch(PETEHandle pte,MenuHandle contextMenu)
|
||
{
|
||
MenuHandle mh = GetMHandle(FIND_HIER_MENU);
|
||
|
||
if (mh && IsMenuItemEnabled(mh,FIND_SEARCH_WEB_ITEM))
|
||
{
|
||
if (CountMenuItems(contextMenu) && !MenuItemIsSeparator(contextMenu,CountMenuItems(contextMenu)))
|
||
AppendMenu(contextMenu,"\p-"); // add a divider
|
||
CopyMenuItem(mh,FIND_SEARCH_WEB_ITEM,contextMenu,REAL_BIG);
|
||
SetMenuItemCommandID(contextMenu,CountMenuItems(contextMenu),(GetMenuID(mh)<<16)|FIND_SEARCH_WEB_ITEM);
|
||
return noErr;
|
||
}
|
||
return fnfErr;
|
||
}
|
||
#endif //CONTEXT_SEARCH
|
||
|
||
/**********************************************************************
|
||
* PeteEditWFocus - edit, switching focus if need be
|
||
**********************************************************************/
|
||
OSErr PeteEditWFocus(MyWindowPtr win,PETEHandle ph,PETEEditEnum what,EventRecord* event,Boolean *activated)
|
||
{
|
||
OSErr err;
|
||
|
||
// (jp) Stuff to handle nickname hiliting/completion/expansion for any PETE
|
||
if (ph && HasNickScanCapability (ph))
|
||
NicknameWatcherFocusChange (ph);
|
||
|
||
err = PeteEdit(win,ph,what,event);
|
||
|
||
if (activated) *activated = False;
|
||
|
||
if (err==tsmDocNotActiveErr)
|
||
{
|
||
PeteFocus(win,ph,True);
|
||
if (activated) *activated = True;
|
||
err=PeteEdit(win,ph,what,event);
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSelect - select stuff, then set proper flags
|
||
**********************************************************************/
|
||
void PeteSelect(MyWindowPtr win,PETEHandle pte,long start,long stop)
|
||
{
|
||
PETEStyleEntry pse;
|
||
|
||
if (!PeteIsValid(pte)) return;
|
||
PETESelect(PETE,pte,start,stop);
|
||
PeteStyleAt(pte,-1,&pse);
|
||
if (start==stop && (pse.psStyle.textStyle.tsLock&peClickAfterLock))
|
||
pse.psStyle.textStyle.tsLock = 0;
|
||
pse.psStyle.textStyle.tsLabel = 0;
|
||
PETESetTextStyle(PETE,pte,-2,-2,&pse.psStyle.textStyle,peAllValid);
|
||
if (win && win->pte==pte) win->hasSelection = MyWinHasSelection(win);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteResetCurStyle - Copy default style into current style
|
||
**********************************************************************/
|
||
void PeteResetCurStyle(PETEHandle pte)
|
||
{
|
||
PETEStyleEntry pse;
|
||
|
||
if (!PeteStyleAt(pte,kPETEDefaultStyle,&pse))
|
||
PETESetTextStyle(PETE,pte,kPETECurrentStyle,kPETECurrentStyle,&pse.psStyle.textStyle,peAllValid);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteWhompHiliteRegionBecausePeteWontFixIt - force editor to recalc hilite
|
||
**********************************************************************/
|
||
OSErr PeteWhompHiliteRegionBecausePeteWontFixIt(PETEHandle pte)
|
||
{
|
||
long start, stop;
|
||
OSErr err;
|
||
|
||
err = PeteGetTextAndSelection(pte,nil,&start,&stop);
|
||
if (!err) PeteSelect(nil,pte,start,stop);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteLock - lock/unlock some text
|
||
**********************************************************************/
|
||
OSErr PeteLock(PETEHandle pte,long start,long stop,short lock)
|
||
{
|
||
PETEStyleEntry pse;
|
||
|
||
pse.psStyle.textStyle.tsLock = lock;
|
||
return(PETESetTextStyle(PETE,pte,start,stop,&pse.psStyle.textStyle,peLockValid));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteFontAndSize - change font & size in a pete record
|
||
**********************************************************************/
|
||
OSErr PeteFontAndSize(PETEHandle pte,short fontID,short size)
|
||
{
|
||
PETEDefaultFontEntry defaultFont;
|
||
OSErr err;
|
||
Str255 fontName;
|
||
|
||
if (fontID==kPETEDefaultFont && size==kPETEDefaultSize)
|
||
return(PETESetDefaultFont(PETE,pte,nil));
|
||
else
|
||
{
|
||
Zero(defaultFont);
|
||
defaultFont.pdFont = fontID;
|
||
defaultFont.pdSize = size;
|
||
err = PETESetDefaultFont(PETE,pte,&defaultFont);
|
||
if (pte) // gotta set a print font if changing the default font for a particular edit region
|
||
{
|
||
defaultFont.pdFont = GetFontID(GetPref(fontName,PREF_PRINT_FONT));
|
||
defaultFont.pdSize = GetPrefLong(PREF_PRINT_FONT_SIZE);
|
||
if (!defaultFont.pdSize) defaultFont.pdSize = FontSize;
|
||
defaultFont.pdPrint = True;
|
||
PETESetDefaultFont(PETE,pte,&defaultFont);
|
||
}
|
||
return(err);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteGraphicHandle - return a PETeGraphicInfoHandle
|
||
**********************************************************************/
|
||
PETEGraphicInfoHandle PeteGraphicHandle(PicHandle thePic, short resId)
|
||
{
|
||
struct PetePictInfo {
|
||
PETEGraphicInfo gi;
|
||
PicHandle pict;
|
||
long counter;
|
||
} **newGHndl;
|
||
|
||
if (!thePic)
|
||
{
|
||
thePic = GetResource_('PICT',resId);
|
||
if (!thePic) return(nil);
|
||
HNoPurge((Handle)thePic);
|
||
}
|
||
|
||
newGHndl = NuHandleClear(sizeof(struct PetePictInfo));
|
||
if(newGHndl != nil) {
|
||
(**newGHndl).gi.itemProc = nil;
|
||
(**newGHndl).gi.width = RectWidth(&(**thePic).picFrame);
|
||
(**newGHndl).gi.height = RectHeight(&(**thePic).picFrame) + 1;
|
||
(**newGHndl).gi.descent = 0L;
|
||
(**newGHndl).pict = thePic;
|
||
(**newGHndl).counter = 1L;
|
||
}
|
||
return (PETEGraphicInfoHandle)newGHndl;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteTextStyleDiff - take the difference of two styles
|
||
**********************************************************************/
|
||
short PeteTextStyleDiff(PETETextStylePtr s1, PETETextStylePtr s2)
|
||
{
|
||
long diff = 0;
|
||
PETEStyleEntry pse1, pse2;
|
||
|
||
Zero(pse1);
|
||
Zero(pse2);
|
||
pse1.psStyle.textStyle = *s1;
|
||
pse2.psStyle.textStyle = *s2;
|
||
|
||
PETECompareStyles(PETE,nil,&pse1,&pse2,peFaceValid|peSizeValid|peFontValid|peColorValid,false,&diff);
|
||
return(diff);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteParaInfoDiff - take the difference of two ParaInfo's
|
||
**********************************************************************/
|
||
short PeteParaInfoDiff(PETEParaInfoPtr s1, PETEParaInfoPtr s2)
|
||
{
|
||
short diff = 0;
|
||
|
||
if (s1->startMargin!=s2->startMargin) diff |= peStartMarginValid;
|
||
if (s1->endMargin!=s2->endMargin) diff |= peEndMarginValid;
|
||
if (s1->indent!=s2->indent) diff |= peIndentValid;
|
||
if (s1->justification!=s2->justification) diff |= peJustificationValid;
|
||
if (s1->quoteLevel!=s2->quoteLevel) diff |= peQuoteLevelValid;
|
||
|
||
return(diff);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteCopy - PeteCopy but using the new routines
|
||
************************************************************************/
|
||
OSErr PeteCopy(PETEHandle fromPTE, PETEHandle toPTE,long fromFrom, long fromTo, long toTo, long *endedAt,Boolean flatten)
|
||
{
|
||
Handle text=nil;
|
||
PETEStyleListHandle pslh=nil;
|
||
PETEParaScrapHandle pScrap=nil;
|
||
OSErr err;
|
||
long len;
|
||
|
||
len = PETEGetTextLen(PETE,fromPTE);
|
||
if (fromTo>len) fromTo = len;
|
||
if (fromFrom>=fromTo) return(noErr);
|
||
err = PeteGetTextStyleScrap(fromPTE,fromFrom,fromTo,&text,&pslh,&pScrap);
|
||
if (flatten)
|
||
{
|
||
ZapPeteStyleScrap(pslh);
|
||
ZapPeteParaScrap(pScrap);
|
||
}
|
||
|
||
if (!err)
|
||
{
|
||
if (toTo==-1) toTo = PeteBumpSelection(toPTE,0);
|
||
len = GetHandleSize(text);
|
||
err = PETEInsertTextScrap(PETE,toPTE,toTo,text,pslh,pScrap,true);
|
||
if (!err && endedAt)
|
||
*endedAt = toTo + len;
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteCopyNoLabel - copy but clear label
|
||
************************************************************************/
|
||
OSErr PeteCopyNoLabel(PETEHandle fromPTE, PETEHandle toPTE,long fromFrom, long fromTo, long toTo, long *endedAt,Boolean flatten,long labelMask)
|
||
{
|
||
long localEnded;
|
||
OSErr err;
|
||
|
||
err = PeteCopy(fromPTE,toPTE,fromFrom,fromTo,toTo,&localEnded,flatten);
|
||
if (!err)
|
||
{
|
||
if (endedAt) *endedAt = localEnded;
|
||
if (labelMask) PetePlain(toPTE,toTo,localEnded,labelMask<<kPETELabelShift);
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* PeteCopyOld - copy stuff from one pete record to another
|
||
**********************************************************************/
|
||
OSErr PeteCopyOld(PETEHandle fromPTE, PETEHandle toPTE,long fromFrom, long fromTo, long toTo, long *endedAt, Boolean flatten)
|
||
{
|
||
long fromPara, toPara;
|
||
OSErr err=noErr;
|
||
|
||
fromPara = PeteParaAt(fromPTE,fromFrom);
|
||
toPara = PeteParaAt(fromPTE,fromTo);
|
||
|
||
while (fromPara<=toPara)
|
||
{
|
||
if (err=PeteCopyPara(fromPTE,toPTE,fromPara,fromFrom,fromTo,toTo,&toTo,flatten))
|
||
break;
|
||
fromPara++;
|
||
}
|
||
if (!err && endedAt) *endedAt = toTo;
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteCopyPara - copy stuff from one pete record to another
|
||
**********************************************************************/
|
||
OSErr PeteCopyPara(PETEHandle fromPTE, PETEHandle toPTE,long fromPara,long fromFrom, long fromTo, long toTo, long *endedAt, Boolean flatten)
|
||
{
|
||
long toPara;
|
||
OSErr err=noErr;
|
||
PETEParaInfo pinfo;
|
||
long runLen;
|
||
PETEStyleEntry pse;
|
||
UHandle text;
|
||
UHandle newText=nil;
|
||
long copied;
|
||
Boolean newBreak;
|
||
|
||
/*
|
||
* figure out where we are
|
||
*/
|
||
toPara = PeteParaAt(toPTE,toTo);
|
||
|
||
/*
|
||
* figure out how long the paragraph is
|
||
*/
|
||
pinfo.tabHandle = nil;
|
||
PETEGetParaInfo(PETE,fromPTE,fromPara,&pinfo);
|
||
|
||
/*
|
||
* don't copy from before the beginning or past the end of the paragraph
|
||
*/
|
||
fromTo = MIN(fromTo,pinfo.paraOffset+pinfo.paraLength);
|
||
fromFrom = MAX(fromFrom,pinfo.paraOffset);
|
||
|
||
/*
|
||
* prefill with the default style
|
||
*/
|
||
PeteGetStyle(toPTE,kPETEDefaultStyle,nil,&pse);
|
||
pse.psStartChar = 0;
|
||
(*Pslh)->psStyle.textStyle = pse.psStyle.textStyle;
|
||
|
||
/*
|
||
* get hold of the text
|
||
*/
|
||
PETEGetRawText(PETE,fromPTE,&text);
|
||
|
||
/*
|
||
* copy the style runs one at a time
|
||
*/
|
||
while (fromFrom<fromTo)
|
||
{
|
||
// get the run information
|
||
PeteGetStyle(fromPTE,fromFrom,&runLen,&pse);
|
||
|
||
// turn runLen into an absolute end of run
|
||
runLen += pse.psStartChar;
|
||
|
||
// don't copy beyond the end of the interesting bit
|
||
runLen = MIN(runLen,fromTo);
|
||
|
||
#ifdef NEVER // dunno what point this served; maybe because the scanner would scan? Anyway, it's in the way now.
|
||
// if the style is a URL, forget the style change
|
||
if (!(pse.psStyle.textStyle.tsLabel&(pURLLabel|pLinkLabel)))
|
||
#endif
|
||
{
|
||
**Pslh = pse;
|
||
}
|
||
|
||
// We don't want to worry about an offset
|
||
(*Pslh)->psStartChar = 0;
|
||
|
||
// copy the data
|
||
newText = NuHTempBetter(runLen-fromFrom);
|
||
if (!newText) {err = MemError(); break;}
|
||
BMD(*text+fromFrom,*newText,runLen-fromFrom);
|
||
copied = runLen-fromFrom;
|
||
fromFrom = runLen;
|
||
|
||
// insert the data
|
||
err = PETEInsertText(PETE,toPTE,toTo,newText,Pslh);
|
||
if (!err) newText = nil;
|
||
else break;
|
||
|
||
// need a paragraph break?
|
||
if (!flatten)
|
||
{
|
||
PeteEnsureBreakLo(toPTE,toTo,&newBreak);
|
||
if (newBreak) toPara++;
|
||
pinfo.paraFlags &= ~peNoParaPaste;
|
||
//Stlyed Text - prevent margins from making it into replies, etc.
|
||
if (HasFeature (featureStyleMargin))
|
||
PETESetParaInfo(PETE,toPTE,toPara,&pinfo,peAllParaValidButTabs);
|
||
else
|
||
PETESetParaInfo(PETE,toPTE,toPara,&pinfo,peAllParaValidButTabs & ~(peJustificationValid|peStartMarginValid|peEndMarginValid));
|
||
flatten = True; // copy paragraph info only once
|
||
}
|
||
|
||
// new offset to copy to
|
||
toTo += copied;
|
||
}
|
||
ZapHandle(newText);
|
||
|
||
if (endedAt) *endedAt = toTo;
|
||
|
||
return(err);
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
/**********************************************************************
|
||
* PeteDump - dump a pete handle to the debugger
|
||
**********************************************************************/
|
||
OSErr PeteDumpLo(PETEHandle pte,short file,short line)
|
||
{
|
||
PETEStyleListHandle pslh=nil;
|
||
OSErr err;
|
||
short para;
|
||
Str255 s, s2;
|
||
PeteExtra extra = **PeteExtra(pte);
|
||
long sel1,sel2;
|
||
UHandle text;
|
||
PETEParaInfo pinfo;
|
||
short run;
|
||
long runLen;
|
||
long numRuns;
|
||
PETETextStyle pts;
|
||
PETEGraphicStyle pgs;
|
||
PETEStyleEntry pse;
|
||
|
||
// Some overall stats
|
||
GetWTitle(GetMyWindowWindowPtr(extra.win),s);
|
||
EscapeInHex(s,s);
|
||
PeteGetTextAndSelection(pte,&text,&sel1,&sel2);
|
||
ComposeLogS(-1,nil,"\p{%d:%d} pte %x len %x sel %d,%d win %p",file,line,pte,PeteLen(pte),sel1,sel2,s);
|
||
|
||
// Current and default styles
|
||
PeteStyleAt(pte,kPETECurrentStyle,&pse);
|
||
pts = pse.psStyle.textStyle;
|
||
pgs = pse.psStyle.graphicStyle;
|
||
// print the common style info
|
||
ComposeString(s,"\p Current graphic %d font %d size %d face %x lock %x label %x ",
|
||
pse.psGraphic, pts.tsFont, pts.tsSize, pts.tsFace,
|
||
pts.tsLock, pts.tsLabel);
|
||
// add color or graphic
|
||
if (pse.psGraphic)
|
||
ComposeString(s2,"\pgi %x",pgs.graphicInfo);
|
||
else
|
||
ComposeString(s2,"\pcolor %d.%d.%d",pts.tsColor.red,pts.tsColor.green,pts.tsColor.blue);
|
||
PSCat(s,s2);
|
||
Log(-1,s);
|
||
PeteStyleAt(pte,kPETEDefaultStyle,&pse);
|
||
pts = pse.psStyle.textStyle;
|
||
pgs = pse.psStyle.graphicStyle;
|
||
// print the common style info
|
||
ComposeString(s,"\p Default graphic %d font %d size %d face %x lock %x label %x ",
|
||
pse.psGraphic, pts.tsFont, pts.tsSize, pts.tsFace,
|
||
pts.tsLock, pts.tsLabel);
|
||
// add color or graphic
|
||
if (pse.psGraphic)
|
||
ComposeString(s2,"\pgi %x",pgs.graphicInfo);
|
||
else
|
||
ComposeString(s2,"\pcolor %d.%d.%d",pts.tsColor.red,pts.tsColor.green,pts.tsColor.blue);
|
||
PSCat(s,s2);
|
||
Log(-1,s);
|
||
|
||
for (para=0;;para++)
|
||
{
|
||
Zero(pinfo);
|
||
if (err=PETEGetParaInfo(PETE,pte,para,&pinfo)) break;
|
||
|
||
// paragraph stats
|
||
ComposeLogS(-1,nil,"\ppara %d offset %d len %d flags %x quote %d sign %d sm %d em %d in %d",
|
||
para,pinfo.paraOffset,pinfo.paraLength,pinfo.paraFlags,pinfo.quoteLevel,pinfo.signedLevel,
|
||
pinfo.startMargin,pinfo.endMargin,pinfo.indent);
|
||
|
||
// Grab the style runs
|
||
if (err=PETEGetDebugStyleScrap(PETE,pte,para,&pslh)) break;
|
||
|
||
numRuns = HandleCount(pslh);
|
||
for (run=0;run<numRuns;run++)
|
||
{
|
||
runLen = (run<numRuns-1 ? (*pslh)[run+1].psStartChar : pinfo.paraLength) - (*pslh)[run].psStartChar;
|
||
// text
|
||
if (runLen>0)
|
||
{
|
||
PCopy(s,"\p <20>");
|
||
if (runLen<64)
|
||
{
|
||
MakePStr(s2,*text+pinfo.paraOffset+(*pslh)[run].psStartChar,runLen);
|
||
EscapeInHex(s2,s2);
|
||
PSCat(s,s2);
|
||
}
|
||
else
|
||
{
|
||
MakePStr(s2,*text+pinfo.paraOffset+(*pslh)[run].psStartChar,31);
|
||
EscapeInHex(s2,s2);
|
||
PSCat(s,s2);
|
||
PSCatC(s,'<EFBFBD>');
|
||
MakePStr(s2,*text+pinfo.paraOffset+(*pslh)[run].psStartChar+runLen-31,31);
|
||
EscapeInHex(s2,s2);
|
||
PSCat(s,s2);
|
||
}
|
||
PCat(s,"\p<EFBFBD>");
|
||
Log(-1,s);
|
||
}
|
||
|
||
// Style info
|
||
pts = (*pslh)[run].psStyle.textStyle;
|
||
pgs = (*pslh)[run].psStyle.graphicStyle;
|
||
// print the common style info
|
||
ComposeString(s,"\p run %d len %d graphic %d font %d size %d face %x lock %x label %x ",
|
||
run, runLen, (*pslh)[run].psGraphic, pts.tsFont, pts.tsSize, pts.tsFace,
|
||
pts.tsLock, pts.tsLabel);
|
||
// add color or graphic
|
||
if ((*pslh)[run].psGraphic)
|
||
ComposeString(s2,"\pgi %x",pgs.graphicInfo);
|
||
else
|
||
ComposeString(s2,"\pcolor %d.%d.%d",pts.tsColor.red,pts.tsColor.green,pts.tsColor.blue);
|
||
PSCat(s,s2);
|
||
Log(-1,s);
|
||
|
||
}
|
||
ZapHandle(pslh); // not a real style scrap!
|
||
}
|
||
CloseLog();
|
||
if (err==errAEImpossibleRange) err = noErr;
|
||
|
||
return(err);
|
||
}
|
||
|
||
#endif
|
||
|
||
/**********************************************************************
|
||
* PeteCleanList - mark all pte's as dirty
|
||
**********************************************************************/
|
||
void PeteCleanList(PETEHandle pte)
|
||
{
|
||
for (;pte;pte=PeteNext(pte))
|
||
PETEMarkDocDirty(PETE,pte,False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteDirty - is a pete dirty?
|
||
**********************************************************************/
|
||
long PeteIsDirty(PETEHandle pte)
|
||
{
|
||
PETEDocInfo info;
|
||
|
||
if (PeteIsValid(pte))
|
||
{
|
||
if (!PETEGetDocInfo(PETE,pte,&info))
|
||
return(info.dirty);
|
||
else
|
||
return(False);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteDirtyList - is any pete dirty?
|
||
**********************************************************************/
|
||
Boolean PeteIsDirtyList(PETEHandle pte)
|
||
{
|
||
for (;pte;pte=PeteNext(pte))
|
||
if (PeteIsDirty(pte)) return(True);
|
||
return(False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteChanged - set the dirty bit on the window when an edit region changes
|
||
**********************************************************************/
|
||
pascal OSErr PeteChanged(PETEHandle pte,long start,long stop)
|
||
{
|
||
MyWindowPtr win;
|
||
|
||
win = (*PeteExtra(pte))->win;
|
||
win->isDirty = True;
|
||
if (start<0) start = 0;
|
||
PeteSetURLRescan(pte,start);
|
||
NicknameWatcherMaybeModifiedField (pte);
|
||
return noErr;
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* DefaultPII - setup defaults
|
||
**********************************************************************/
|
||
void DefaultPII(MyWindowPtr win,Boolean ro,uLong flags,PETEDocInitInfoPtr pdi)
|
||
{
|
||
Zero(*pdi);
|
||
pdi->inWindow = GetMyWindowWindowPtr(win);
|
||
pdi->inRect = win->contR;
|
||
pdi->inRect.top = -30;
|
||
pdi->inRect.bottom = -5;
|
||
pdi->docWidth = -1;
|
||
pdi->inStyle.tsFont = kPETEDefaultFont; //((GrafPtr)win)->txFont;
|
||
#ifdef USERELATIVESIZES
|
||
pdi->inStyle.tsSize = kPETERelativeSizeBase; //((GrafPtr)win)->txSize;
|
||
#else
|
||
pdi->inStyle.tsSize = kPETEDefaultSize; //((GrafPtr)win)->txSize;
|
||
#endif
|
||
DEFAULT_COLOR(pdi->inStyle.tsColor);
|
||
if (ro) pdi->inStyle.tsLock = peModLock;
|
||
if (GetPrefLong(PREF_DRAG_OPTIONS)&2) flags |= peDragOnControl;
|
||
pdi->docFlags = flags;
|
||
DefaultPPI(&pdi->inParaInfo);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSetupTextColors - set the default colors
|
||
**********************************************************************/
|
||
void PeteSetupTextColors(PETEHandle pte,Boolean black)
|
||
{
|
||
PETELabelStyleEntry pls;
|
||
|
||
Zero(pls);
|
||
|
||
pls.plColorWeight = GetRLong(QUOTE_BLEND);
|
||
if (!black) GetRColor(&pls.plColor,QUOTE_COLOR);
|
||
|
||
// Quotes and quoted stationery
|
||
pls.plValidBits = peColorValid;
|
||
pls.plLabel = pQuoteLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pQuoteLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
|
||
// Recognized url's
|
||
pls.plColorWeight = 100;
|
||
if (!black) GetRTextColor(&pls.plColor,URL_COLOR);
|
||
pls.plFace = GetRLong(URL_STYLE);
|
||
pls.plValidBits = peColorValid|pls.plFace;
|
||
pls.plLabel = pURLLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel |= pQuoteLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pURLLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel |= pQuoteLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
|
||
// HTML links
|
||
if (!black) GetRTextColor(&pls.plColor,LINK_COLOR);
|
||
pls.plFace = GetRLong(LINK_STYLE);
|
||
pls.plLabel = pLinkLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pLinkLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pLinkLabel|pQuoteLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pLinkLabel|pQuoteLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
|
||
// Weird reply-to lines
|
||
pls.plValidBits = peColorValid;
|
||
if (!black) GetRTextColor(&pls.plColor,REPLY_COLOR);
|
||
pls.plLabel = pReplyLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
|
||
// Background and foreground colors
|
||
if (!black) GetRColor(&pls.plColor,TEXT_COLOR);
|
||
PETESetDefaultColor(PETE,pte,&pls.plColor);
|
||
GetRColor(&pls.plColor,BACK_COLOR);
|
||
PETESetDefaultBGColor(PETE,pte,&pls.plColor);
|
||
|
||
// and the speller
|
||
#ifdef WINTERTREE
|
||
if (HasFeature (featureSpellChecking)) {
|
||
if (!black) GetRTextColor(&pls.plColor,SPELL_COLOR);
|
||
pls.plFace = GetRLong(SPELL_FACE);
|
||
pls.plValidBits = peColorValid|pls.plFace;
|
||
pls.plLabel = pSpellLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pSpellLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
}
|
||
#endif
|
||
|
||
if (HasFeature (featureAnal)) {
|
||
if (!black) GetRTextColor(&pls.plColor,MOOD_COLOR);
|
||
pls.plFace = GetRLong(MOOD_FACE);
|
||
pls.plValidBits = peColorValid|pls.plFace;
|
||
pls.plLabel = pTightAnalLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pTightAnalLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pTightAnalLabel|pSpellLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pTightAnalLabel|pStationeryLabel|pSpellLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
if (!black) GetRTextColor(&pls.plColor,MOOD_H_COLOR);
|
||
pls.plFace = GetRLong(MOOD_H_FACE);
|
||
pls.plValidBits = peColorValid|pls.plFace;
|
||
pls.plLabel = pLooseAnalLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pLooseAnalLabel|pStationeryLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pLooseAnalLabel|pSpellLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
pls.plLabel = pLooseAnalLabel|pStationeryLabel|pSpellLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
}
|
||
|
||
// nickname hiliting
|
||
pls.plFace = (GetRLong(NICK_STYLE)&0xFF);
|
||
pls.plValidBits = pls.plFace;
|
||
if (!black) GetRTextColor(&pls.plColor, NICK_COLOR);
|
||
if (!IsPETEDefaultColor(pls.plColor)) pls.plValidBits |= peColorValid;
|
||
pls.plLabel = pNickHiliteLabel; PETESetLabelStyle(PETE,pte,&pls);
|
||
|
||
// autoscroll
|
||
PETEAutoScrollTicks(PETE,GetRLong(SCROLL_THROTTLE)-1);
|
||
}
|
||
|
||
#if defined(NEVER)
|
||
/**********************************************************************
|
||
* PeteSetRudeColor - set the colors for rude url's
|
||
**********************************************************************/
|
||
void PeteSetRudeColor(void)
|
||
{
|
||
PETELabelStyleEntry pls;
|
||
|
||
Zero(pls);
|
||
pls.plColor.blue = Random();
|
||
pls.plColor.green = Random();
|
||
pls.plColor.red = Random();
|
||
DarkenColor(&pls.plColor,30);
|
||
pls.plFace = GetRLong(URL_STYLE);
|
||
pls.plValidBits = peColorValid|pls.plFace;
|
||
pls.plLabel = pRudeURLLabel; PETESetLabelStyle(PETE,nil,&pls);
|
||
}
|
||
#endif
|
||
|
||
/**********************************************************************
|
||
* DefaultPPI - default paragraph info
|
||
**********************************************************************/
|
||
PETEParaInfoPtr DefaultPPI(PETEParaInfoPtr ppi)
|
||
{
|
||
long size;
|
||
|
||
size = GetRLong(TAB_DISTANCE)*FontWidth;
|
||
Zero(*ppi);
|
||
|
||
ppi->tabHandle = (void*)NuHandle(sizeof(**(ppi->tabHandle)));
|
||
if (ppi->tabHandle)
|
||
{
|
||
ppi->tabCount = kPETEFixedTab;
|
||
**ppi->tabHandle = size;
|
||
}
|
||
|
||
ppi->startMargin = ppi->endMargin = -1;
|
||
ppi->justification = teFlushLeft;
|
||
ppi->paraFlags = peTextOnly | peNoParaPaste | pePlainTextOnly;
|
||
|
||
ppi->direction = kHilite; // Default system direction
|
||
|
||
return(ppi);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteParaSelect - select the current text, all the way out to the
|
||
* paragraph boundaries
|
||
**********************************************************************/
|
||
OSErr PeteParaRange(PETEHandle pte,long *startPtr, long *endPtr)
|
||
{
|
||
UHandle text;
|
||
long start,end;
|
||
long paraPoint;
|
||
PETEParaInfo pinfo;
|
||
long pIndex;
|
||
OSErr err;
|
||
|
||
if (err=PeteGetTextAndSelection(pte,&text,&start,&end)) return(err);
|
||
if (startPtr && *startPtr!=-1) start = *startPtr;
|
||
if (endPtr && *endPtr!=-1) end = *endPtr;
|
||
pinfo.tabHandle = nil;
|
||
|
||
/*
|
||
* beginning
|
||
*/
|
||
pIndex = PeteParaAt(pte,start);
|
||
PETEGetParaInfo(PETE,pte,pIndex,&pinfo);
|
||
while (start>pinfo.paraOffset && (*text)[start-1]!='\015') start--;
|
||
|
||
/*
|
||
* end
|
||
*/
|
||
pIndex = PeteParaAt(pte,end);
|
||
PETEGetParaInfo(PETE,pte,pIndex,&pinfo);
|
||
paraPoint = pinfo.paraOffset+pinfo.paraLength;
|
||
if (start<paraPoint) end = MAX(end,start+1); // try not to look at the same return start did
|
||
while (end<paraPoint && (*text)[end-1]!='\015') end++;
|
||
|
||
if (startPtr) *startPtr = start;
|
||
if (endPtr) *endPtr = end;
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteEnsureRangeBreak - make sure returns near us have breaks
|
||
**********************************************************************/
|
||
OSErr PeteEnsureRangeBreak(PETEHandle pte,long start,long stop)
|
||
{
|
||
OSErr err = PeteParaRange(pte,&start,&stop);
|
||
if (!err) err = PeteEnsureBreak(pte,start);
|
||
if (!err) err = PeteEnsureBreak(pte,stop);
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteParaConvert - convert text to separate paragraphs
|
||
**********************************************************************/
|
||
OSErr PeteParaConvert(PETEHandle pte,long start,long end)
|
||
{
|
||
UHandle text;
|
||
PETEParaInfo pinfo;
|
||
Boolean bitterEnd = end >= PETEGetTextLen(PETE,pte);
|
||
long len = PeteLen(pte);
|
||
|
||
PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
pinfo.tabHandle = nil;
|
||
if (end<len) end++;
|
||
else end = len;
|
||
|
||
if (start<0) start = 0;
|
||
|
||
while (start<=end)
|
||
{
|
||
if (start && (*text)[start-1]=='\015')
|
||
PeteEnsureBreak(pte,start);
|
||
start++;
|
||
}
|
||
|
||
if (bitterEnd) PeteEnsureTrailingEmpty(pte);
|
||
|
||
return(noErr);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteEnsureTrailingEmpty - make sure the last paragraph is empty
|
||
************************************************************************/
|
||
OSErr PeteEnsureTrailingEmpty(PETEHandle pte)
|
||
{
|
||
long lastPara;
|
||
long len = PETEGetTextLen(PETE,pte);
|
||
OSErr err = PETEGetParaIndex(PETE,pte,len+1,&lastPara);
|
||
PETEParaInfo info;
|
||
Handle text;
|
||
|
||
if (len && !err)
|
||
{
|
||
Zero(info);
|
||
PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
if ((*text)[len-1]=='\015' && !(err=PETEGetParaInfo(PETE,pte,lastPara,&info)))
|
||
if (info.paraLength)
|
||
//last para is non-empty. Add one
|
||
err = PETEInsertParaBreak(PETE,pte,PETEGetTextLen(PETE,pte));
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteEnsureBreakLo(PETEHandle pte,long inOffset,Boolean *did)
|
||
{
|
||
PETEParaInfo pinfo;
|
||
long offset;
|
||
long pIndex;
|
||
OSErr err = noErr;
|
||
|
||
if (did) *did = False;
|
||
|
||
if (inOffset==-1) PeteGetTextAndSelection(pte,nil,&offset,nil);
|
||
else offset = inOffset;
|
||
|
||
if (offset>1)
|
||
{
|
||
Zero(pinfo);
|
||
pIndex = PeteParaAt(pte,offset-1);
|
||
PETEGetParaInfo(PETE,pte,pIndex,&pinfo);
|
||
if (pinfo.paraOffset+pinfo.paraLength!=offset || inOffset==-1&&pinfo.paraLength)
|
||
{
|
||
#ifdef DEBUG
|
||
ASSERT(PeteCrAt(pte,offset-1) || offset==PeteLen(pte));
|
||
#endif
|
||
err = PETEInsertParaBreak(PETE,pte,offset);
|
||
if (!err && did) *did = True;
|
||
}
|
||
}
|
||
return err;
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteEnsureCrAndBreak - make sure there's a cr and a break at the offset
|
||
************************************************************************/
|
||
OSErr PeteEnsureCrAndBreakLo(PETEHandle pte, long inOffset, long *newOffset,Boolean *did)
|
||
{
|
||
long offset,selEnd;
|
||
UHandle textH;
|
||
OSErr err = noErr;
|
||
|
||
|
||
// Grab the text handle, find out where the insertion point is
|
||
PeteGetTextAndSelection(pte,&textH,&offset,&selEnd);
|
||
|
||
// Have we been given an absolute offset that happens to be
|
||
// the insertion point?
|
||
if (inOffset==offset) inOffset = -1;
|
||
|
||
// If we've been given an offset, use that
|
||
if (inOffset!=-1) offset = inOffset;
|
||
|
||
// Work to do?
|
||
if (offset && (*textH)[offset-1]!='\015')
|
||
{
|
||
err = PeteInsertChar(pte,offset,'\015',nil);
|
||
if (!err) {
|
||
err = PETEInsertParaBreak(PETE,pte,++offset);
|
||
|
||
if (!err && inOffset==-1) PeteSelect((*PeteExtra(pte))->win,pte,offset,selEnd+1);
|
||
if (did) *did = !err;
|
||
}
|
||
}
|
||
else
|
||
err = PeteEnsureBreakLo(pte,offset,did);
|
||
if (newOffset) *newOffset = offset;
|
||
return(err);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* PeteStringLo - return whole text as string
|
||
**********************************************************************/
|
||
PStr PeteStringLo(PStr string,short size,PETEHandle pte)
|
||
{
|
||
long got;
|
||
|
||
if (!PETEGetTextPtr(PETE,pte,0,size-2,string+1,size-1,&got))
|
||
{
|
||
*string = got;
|
||
string[*string+1] = 0;
|
||
}
|
||
else
|
||
*string = 0;
|
||
return(string);
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteScroll(PETEHandle pte,short horizontal,short vertical)
|
||
{
|
||
return(PETEScroll(PETE,pte,horizontal,vertical));
|
||
}
|
||
#endif
|
||
|
||
/**********************************************************************
|
||
* PeteSetTextPtr - replace entire text
|
||
**********************************************************************/
|
||
OSErr PeteSetTextPtr(PETEHandle pte,UPtr text,long len)
|
||
{
|
||
OSErr err = noErr;
|
||
PeteDelete(pte,0,0x7fffffff);
|
||
PeteScroll(pte,0,pseCenterSelection);
|
||
err = PETEInsertTextPtr(PETE,pte,-1,text,len,nil);
|
||
PeteSetURLRescan(pte,0);
|
||
PeteNickScan (pte);
|
||
return err;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSetTextPtr - replace entire text
|
||
**********************************************************************/
|
||
OSErr PeteSetText(PETEHandle pte,Handle text)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
PeteDelete(pte,0,0x7fffffff);
|
||
PeteScroll(pte,0,pseCenterSelection);
|
||
if (text)
|
||
{
|
||
err = PETEInsertTextPtr(PETE,pte,-1,LDRef(text),GetHandleSize(text),nil);
|
||
UL(text);
|
||
}
|
||
PeteSetURLRescan(pte,0);
|
||
PeteNickScan (pte);
|
||
return err;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSmallParas - make sure pargraphs are reasonable in size
|
||
**********************************************************************/
|
||
void PeteSmallParas(PETEHandle pte)
|
||
{
|
||
long len = PETEGetTextLen(PETE,pte);
|
||
long spot;
|
||
long last = 0;
|
||
Handle text;
|
||
Boolean dirty = 0!=PeteIsDirty(pte);
|
||
|
||
PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
for (spot=0;spot<len;spot++)
|
||
if ((*text)[spot]=='\015' && spot-last>(4 K))
|
||
{
|
||
PeteEnsureBreak(pte,spot+1);
|
||
last = spot;
|
||
}
|
||
PETEMarkDocDirty(PETE,pte,dirty);
|
||
(*PeteExtra(pte))->win->isDirty = dirty;
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void PeteUpdate(PETEHandle pte)
|
||
{
|
||
MyWindowPtr win = (*PeteExtra(pte))->win;
|
||
|
||
if ((*PeteExtra(pte))->frame)
|
||
{
|
||
PeteFrame(pte,nil);
|
||
if (!InBG && win->isActive && win->pte==pte)
|
||
PeteHotRect(pte,!(*PeteExtra(pte))->isInactive);
|
||
}
|
||
PushGWorld();
|
||
RGBBackColor(&win->backColor);
|
||
PETEDraw(PETE,pte);
|
||
PopGWorld();
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteFrame - put a border around a PETE edit region
|
||
**********************************************************************/
|
||
void PeteFrame(PETEHandle pte,RGBColor *baseColor)
|
||
{
|
||
PETEDocInfo info;
|
||
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
|
||
if (!baseColor) DrawThemeEditTextFrame(&info.docRect,(*PeteExtra(pte))->win->isActive && !(*PeteExtra(pte))->isInactive ?kThemeStateActive:kThemeStateInactive);
|
||
else Frame3DOrNot(&info.docRect,baseColor,False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteHotRect - put a focus ring around a PETE edit region
|
||
**********************************************************************/
|
||
void PeteHotRect(PETEHandle pte,Boolean on)
|
||
{
|
||
PETEDocInfo info;
|
||
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
PushGWorld();
|
||
SetPort_(GetMyWindowCGrafPtr((*PeteExtra(pte))->win));
|
||
if (on) DrawThemeFocusRect(&info.docRect,on);
|
||
else
|
||
{
|
||
RgnHandle rgn = NewRgn();
|
||
if (rgn)
|
||
{
|
||
MyWindowPtr win = (*PeteExtra(pte))->win;
|
||
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
||
|
||
RectRgn(rgn,&info.docRect);
|
||
InsetRgn(rgn,-MAX_APPEAR_RIM,-MAX_APPEAR_RIM);
|
||
RgnMinusRect(rgn,&info.docRect);
|
||
InvalWindowRgn(winWP,rgn);
|
||
DisposeRgn(rgn);
|
||
}
|
||
}
|
||
PopGWorld();
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteRect - return the rectangle of a pete region
|
||
**********************************************************************/
|
||
Rect *PeteRect(PETEHandle pte,Rect *r)
|
||
{
|
||
PETEDocInfo info;
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
*r = info.docRect;
|
||
return(r);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteRecalc - force pete region to recalc entire region
|
||
************************************************************************/
|
||
void PeteRecalc(PETEHandle pte)
|
||
{
|
||
Boolean dirtyWindow,dirtyPete;
|
||
Rect r;
|
||
RgnHandle oldClip;
|
||
MyWindowPtr pteWin = (*PeteExtra(pte))->win;
|
||
GrafPtr ptePort = GetMyWindowCGrafPtr(pteWin);
|
||
|
||
// Save dirty status
|
||
dirtyPete = PeteIsDirty(pte);
|
||
dirtyWindow = pteWin->isDirty;
|
||
|
||
// Turn off calculations, resize, then restore
|
||
PeteCalcOff(pte);
|
||
|
||
oldClip = SavePortClipRegion(ptePort);
|
||
SetPort_(ptePort);
|
||
SetRect(&r,0,0,0,0);
|
||
ClipRect(&r);
|
||
PeteRect(pte,&r);
|
||
InsetRect(&r,-100,-100);
|
||
PeteDidResize(pte,&r);
|
||
InsetRect(&r,100,100);
|
||
PeteDidResize(pte,&r);
|
||
PeteCalcOn(pte);
|
||
RestorePortClipRegion(ptePort,oldClip);
|
||
|
||
if (!dirtyPete) PETEMarkDocDirty(PETE,pte,false);
|
||
pteWin->isDirty = dirtyWindow;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteRemoveFromRgn - remove the pete rectangles from something
|
||
**********************************************************************/
|
||
RgnHandle PeteRemoveFromRgn(RgnHandle rgn,PETEHandle pte)
|
||
{
|
||
PETEDocInfo info;
|
||
|
||
for (;pte;pte=(*PeteExtra(pte))->next)
|
||
{
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
RgnMinusRect(rgn,&info.docRect);
|
||
}
|
||
return(rgn);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteSelectedString - return selected string
|
||
**********************************************************************/
|
||
PStr PeteSelectedString(PStr string,PETEHandle pte)
|
||
{
|
||
long got;
|
||
PETEDocInfo info;
|
||
|
||
PETEGetDocInfo(PETE,pte,&info);
|
||
*string = 0;
|
||
if (info.selStop>info.selStart)
|
||
{
|
||
info.selStop = MIN(info.selStart+250,info.selStop);
|
||
PETEGetTextPtr(PETE,pte,info.selStart,info.selStop,string+1,253,&got);
|
||
*string = info.selStop-info.selStart;
|
||
string[*string+1] = 0;
|
||
}
|
||
return(string);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteLen - how long is a Pete?
|
||
**********************************************************************/
|
||
long PeteLen(PETEHandle pte)
|
||
{
|
||
return(PETEGetTextLen(PETE,pte));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteGetTextAndSelection - get text handle and current selection
|
||
**********************************************************************/
|
||
OSErr PeteGetTextAndSelection(PETEHandle pte,Handle *textH,long *selStart,long *selEnd)
|
||
{
|
||
OSErr err = fnfErr;
|
||
PETEDocInfo info;
|
||
|
||
if (PeteIsValid(pte))
|
||
{
|
||
if (textH) err = PeteGetRawText(pte,textH);
|
||
else err = noErr;
|
||
if (selStart || selEnd)
|
||
{
|
||
if (err=PETEGetDocInfo(PETE,pte,&info))
|
||
info.selStart = info.selStop = 0;
|
||
if (selStart) *selStart = info.selStart;
|
||
if (selEnd) *selEnd = info.selStop;
|
||
}
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteBumpSelection - move the selection by an increment
|
||
************************************************************************/
|
||
long PeteBumpSelection(PETEHandle pte,long bumpAmount)
|
||
{
|
||
long sel;
|
||
|
||
PeteGetTextAndSelection(pte,nil,&sel,nil);
|
||
if (bumpAmount)
|
||
{
|
||
sel += bumpAmount;
|
||
PeteSelect(nil,pte,sel,sel);
|
||
}
|
||
|
||
return sel;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteGetRawText - get raw text; return empty handle if no text
|
||
**********************************************************************/
|
||
OSErr PeteGetRawText(PETEHandle pte,UHandle *text)
|
||
{
|
||
static UHandle empty;
|
||
OSErr err;
|
||
|
||
*text = nil;
|
||
|
||
err = PETEGetRawText(PETE,pte,text);
|
||
|
||
if (!*text)
|
||
{
|
||
if (!empty) empty=NuHandle(0L);
|
||
if (empty) SetHandleBig_(empty,0);
|
||
*text = empty;
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteCharAt - What character is at an offset?
|
||
**********************************************************************/
|
||
uShort PeteCharAt(PETEHandle pte,long offset)
|
||
{
|
||
UHandle text;
|
||
PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
if (!text || offset<0 || offset>=GetHandleSize(text)) return(0);
|
||
else return((*text)[offset]);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteDelete - delete some text
|
||
**********************************************************************/
|
||
OSErr PeteDelete(PETEHandle pte,long start,long stop)
|
||
{
|
||
if (start==stop && start>=0) return(noErr);
|
||
return(PETEInsertTextPtr(PETE,pte,start,nil,stop-start,nil));
|
||
}
|
||
|
||
/* MJN *//* moved the macros for HLFTAB2FIX and FIX2HLFTAB from here to peteglue.h */
|
||
|
||
/**********************************************************************
|
||
* PeteConvert2Marg - convert from Pete's margin conventions to mine
|
||
**********************************************************************/
|
||
void PeteConvert2Marg(PETEParaInfoPtr pinfo,PSMPtr marg)
|
||
{
|
||
long width = FontWidth*GetRLong(TAB_DISTANCE);
|
||
|
||
if (pinfo->indent<0)
|
||
{
|
||
marg->first = FIX2HLFTAB(pinfo->startMargin+pinfo->indent);
|
||
marg->second = FIX2HLFTAB(pinfo->startMargin);
|
||
}
|
||
else
|
||
{
|
||
marg->first = FIX2HLFTAB(pinfo->startMargin);
|
||
marg->second = marg->first + FIX2HLFTAB(pinfo->indent);
|
||
}
|
||
marg->right = FIX2HLFTAB(-pinfo->endMargin);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteConvertMarg - convert from my margin conventions to Pete's
|
||
**********************************************************************/
|
||
void PeteConvertMarg(PETEHandle pte,long basePara,PSMPtr marg,PETEParaInfoPtr pinfo)
|
||
{
|
||
PETEParaInfo dinfo;
|
||
long width = FontWidth*GetRLong(TAB_DISTANCE);
|
||
|
||
dinfo.tabHandle = nil;
|
||
PETEGetParaInfo(PETE,pte,basePara,&dinfo);
|
||
|
||
/*
|
||
* Pete has a weird mind
|
||
*/
|
||
if (marg->first > marg->second)
|
||
{
|
||
pinfo->startMargin = dinfo.startMargin + HLFTAB2FIX(marg->second);
|
||
pinfo->indent = HLFTAB2FIX(marg->first-marg->second);
|
||
}
|
||
else
|
||
{
|
||
pinfo->startMargin = dinfo.startMargin + HLFTAB2FIX(marg->first);
|
||
pinfo->indent = HLFTAB2FIX(marg->first-marg->second);
|
||
}
|
||
|
||
/*
|
||
* set the end margin
|
||
*/
|
||
pinfo->endMargin = dinfo.endMargin - HLFTAB2FIX(marg->right);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* OSErr PeteParaInset - inset some paragraphs
|
||
**********************************************************************/
|
||
OSErr PeteParaInset(PETEHandle pte,long fromOffset,long toOffset,PSMPtr marg)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
if (marg->first || marg->right)
|
||
{
|
||
long from = PeteParaAt(pte,fromOffset);
|
||
long to = PeteParaAt(pte,toOffset);
|
||
Fixed first, right;
|
||
long width = FontWidth*GetRLong(TAB_DISTANCE);
|
||
PETEParaInfo pinfo;
|
||
|
||
first = HLFTAB2FIX(marg->first);
|
||
right = HLFTAB2FIX(marg->right);
|
||
Zero(pinfo);
|
||
|
||
for (;from<=to;from++)
|
||
{
|
||
if (!(err = PETEGetParaInfo(PETE,pte,from,&pinfo)))
|
||
{
|
||
if (first) pinfo.startMargin += first;
|
||
if (right) pinfo.endMargin -= right;
|
||
err = PETESetParaInfo(PETE,pte,from,&pinfo,peStartMarginValid|peEndMarginValid);
|
||
}
|
||
}
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PETESetTextStyle - set a text style
|
||
**********************************************************************/
|
||
OSErr PETESetTextStyle(PETEInst pi,PETEHandle ph,long start,long stop,PETETextStylePtr textStyle,long validBits)
|
||
{
|
||
return(PETESetStyle(pi,ph,start,stop,(PETEStyleInfoPtr)textStyle,validBits));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteExcerpt - make paragraphs more excerpty
|
||
**********************************************************************/
|
||
OSErr PeteExcerpt(PETEHandle pte,long fromOffset,long toOffset)
|
||
{
|
||
OSErr err = noErr;
|
||
long from = PeteParaAt(pte,fromOffset);
|
||
long to = PeteParaAt(pte,toOffset);
|
||
PETEParaInfo pinfo;
|
||
PETEStyleEntry pse;
|
||
|
||
Zero(pinfo);
|
||
Zero(pse);
|
||
|
||
if (!(err = PETEGetParaInfo(PETE,pte,to,&pinfo)))
|
||
toOffset = pinfo.paraOffset+pinfo.paraLength;
|
||
pse.psStyle.textStyle.tsLabel = pQuoteLabel;
|
||
err = PETESetTextStyle(PETE,pte,fromOffset,toOffset,&pse.psStyle.textStyle,pQuoteLabel<<kPETELabelShift);
|
||
|
||
for (;!err && from<=to;from++)
|
||
{
|
||
if (!(err = PETEGetParaInfo(PETE,pte,from,&pinfo)))
|
||
{
|
||
pinfo.quoteLevel++;
|
||
err = PETESetParaInfo(PETE,pte,from,&pinfo,peQuoteLevelValid);
|
||
}
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteExcerpt - make a particular paragraph a particular level of excerpt
|
||
**********************************************************************/
|
||
OSErr PeteSetExcerptLevelAt(PETEHandle pte,long offsetOfCR,short quoteLevel)
|
||
{
|
||
long para;
|
||
PETEParaInfo pInfo;
|
||
OSErr err;
|
||
PETEStyleEntry pse;
|
||
|
||
// make a paragraph break
|
||
PeteEnsureBreak(pte,offsetOfCR);
|
||
para = PeteParaAt(pte,offsetOfCR);
|
||
|
||
// set its excerpt
|
||
pInfo.quoteLevel = quoteLevel;
|
||
err = PETESetParaInfo(PETE,pte,para,&pInfo,peQuoteLevelValid);
|
||
|
||
// and the quote label
|
||
if (!err)
|
||
{
|
||
Zero(pInfo);
|
||
if (!PETEGetParaInfo(PETE,pte,para,&pInfo))
|
||
{
|
||
pse.psStyle.textStyle.tsLabel = quoteLevel ? pQuoteLabel:0;
|
||
err = PETESetTextStyle(PETE,pte,pInfo.paraOffset,pInfo.paraOffset+pInfo.paraLength,&pse.psStyle.textStyle,peLabelValid);
|
||
}
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteParaAt - what's the paragraph index at an offset?
|
||
**********************************************************************/
|
||
long PeteParaAt(PETEHandle pte,long offset)
|
||
{
|
||
long index;
|
||
|
||
if (PETEGetParaIndex(PETE,pte,offset,&index)) {ASSERT(0);return(-1);}
|
||
else return(index);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteIsExcerptAt - do we have excerpt here?
|
||
************************************************************************/
|
||
short PeteIsExcerptAt(PETEHandle pte,long offset)
|
||
{
|
||
PETEParaInfo pinfo;
|
||
long pIndex = PeteParaAt(pte,offset);
|
||
|
||
Zero(pinfo);
|
||
PETEGetParaInfo(PETE,pte,pIndex,&pinfo);
|
||
return(pinfo.quoteLevel);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteIsBullet - do we have bullet here?
|
||
************************************************************************/
|
||
Boolean PeteIsBullet(PETEHandle pte,long pIndex)
|
||
{
|
||
PETEParaInfo pinfo;
|
||
|
||
Zero(pinfo);
|
||
PETEGetParaInfo(PETE,pte,pIndex,&pinfo);
|
||
return((pinfo.paraFlags&peListBits)!=0);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteIsLabelled - Is something labelled?
|
||
**********************************************************************/
|
||
Boolean PeteIsLabelled(PETEHandle pte,long start,long end,short label)
|
||
{
|
||
long found1, found2;
|
||
|
||
if (PETEFindLabelRun(PETE,pte,start,&found1,&found2,label,label)) return false;
|
||
if (found1>=end) return false;
|
||
return true;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* Ascii2Margin - take a margin descriptor and interpret it
|
||
**********************************************************************/
|
||
OSErr Ascii2Margin(PStr source,PStr name,PSMPtr marg)
|
||
{
|
||
UPtr spot;
|
||
Str255 token;
|
||
|
||
spot=source+1;
|
||
if (!*source) return(fnfErr);
|
||
if (!PToken(source,token,&spot,",")) return(fnfErr);
|
||
if (name) PCopy(name,token);
|
||
if (*token==1 && token[1]=='-') return(noErr);
|
||
if (!PToken(source,token,&spot,",")) return(fnfErr);
|
||
if (marg) StringToNum(token,&marg->first);
|
||
if (!PToken(source,token,&spot,",")) return(fnfErr);
|
||
if (marg) StringToNum(token,&marg->second);
|
||
if (!PToken(source,token,&spot,",")) return(fnfErr);
|
||
if (marg) StringToNum(token,&marg->right);
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* Res2PInfo - take a margin descriptor resource and turn it into a peteparainfo
|
||
**********************************************************************/
|
||
OSErr Res2PInfo(short source,PETEHandle pte,PStr name,PETEParaInfoPtr pinfop)
|
||
{
|
||
Str255 s;
|
||
PeteSaneMargin psm;
|
||
|
||
Ascii2Margin(GetRString(s,source),name,&psm);
|
||
Zero(*pinfop);
|
||
PeteConvertMarg(pte,kPETELastPara,&psm,pinfop);
|
||
return noErr;
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteSaveTEStyles(PETEHandle pte,FSSpecPtr spec)
|
||
{
|
||
OSErr err;
|
||
short refN;
|
||
PETEStyleListHandle pslh=nil;
|
||
StScrpHandle ssh=nil;
|
||
PETEParaScrapHandle paraScrapHandle=nil;
|
||
short oldResF = CurResFile();
|
||
|
||
if (!(err=PeteRemoveTEStyles(spec)))
|
||
if (HasStyles(pte,0,PETEGetTextLen(PETE,pte),false))
|
||
{
|
||
FSpCreateResFile(spec,FileCreatorOf(spec),FileTypeOf(spec),smSystemScript);
|
||
refN = FSpOpenResFile(spec,fsRdWrPerm);
|
||
if (0<=refN)
|
||
{
|
||
if (!(err=PeteGetTextStyleScrap(pte,0,kPETEEndOfText,nil,&pslh,¶ScrapHandle)))
|
||
if (!(err=PETEConvertToTEScrap(PETE,pslh,&ssh)))
|
||
{
|
||
AddResource((Handle)ssh,'styl',128,"");
|
||
if (!(err=ResError()))
|
||
{
|
||
ssh = nil;
|
||
AddResource((Handle)paraScrapHandle,kPETEParaScrap,128,"");
|
||
if (!(err=ResError())) paraScrapHandle = nil;
|
||
}
|
||
}
|
||
CloseResFile(refN);
|
||
if (!err) err = ResError();
|
||
}
|
||
else err = ResError();
|
||
}
|
||
ZapHandle(pslh);
|
||
ZapHandle(ssh);
|
||
ZapHandle(paraScrapHandle);
|
||
UseResFile (oldResF);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr PeteRemoveTEStyles(FSSpecPtr spec)
|
||
{
|
||
OSErr err=noErr;
|
||
short refN;
|
||
Handle resH;
|
||
short oldResF = CurResFile();
|
||
|
||
refN = FSpOpenResFile(spec,fsRdWrPerm);
|
||
if (refN!=-1)
|
||
{
|
||
SetResLoad(False);
|
||
while (resH=Get1IndResource('styl',1))
|
||
{
|
||
SetResLoad(True);
|
||
RemoveResource(resH);
|
||
SetResLoad(False);
|
||
}
|
||
while (resH=Get1IndResource(kPETEParaScrap,1))
|
||
{
|
||
SetResLoad(True);
|
||
RemoveResource(resH);
|
||
SetResLoad(False);
|
||
}
|
||
SetResLoad(True);
|
||
CloseResFile(refN);
|
||
}
|
||
UseResFile (oldResF);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PetePrepareUndo - set up the undo buffer
|
||
**********************************************************************/
|
||
OSErr PetePrepareUndo(PETEHandle pte,short undoWhat,long start,long stop,long *uStart,long *uStop)
|
||
{
|
||
OSErr err;
|
||
|
||
if (start==kPETECurrentSelection) PeteGetTextAndSelection(pte,nil,&start,nil);
|
||
if (stop==kPETECurrentSelection) PeteGetTextAndSelection(pte,nil,nil,&stop);
|
||
if (uStart) *uStart = start;
|
||
if (uStop) *uStop = stop;
|
||
|
||
if ((*PeteExtra(pte))->undoInsertion = start==stop)
|
||
PETEClearUndo(PETE,pte);
|
||
else
|
||
err = PETESetUndo(PETE,pte,start,stop,undoWhat);
|
||
|
||
PETEAllowUndo(PETE,pte,False,False);
|
||
PeteCalcOff(pte);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteFinishUndo - finish up undo stuff
|
||
**********************************************************************/
|
||
OSErr PeteFinishUndo(PETEHandle pte,short undoWhat,long start,long stop)
|
||
{
|
||
OSErr err;
|
||
Boolean select;
|
||
|
||
if (start==kPETECurrentSelection) PeteGetTextAndSelection(pte,nil,&start,nil);
|
||
if (stop==kPETECurrentSelection) PeteGetTextAndSelection(pte,nil,nil,&stop);
|
||
|
||
// turn undoing back on
|
||
PETEAllowUndo(PETE,pte,True,False);
|
||
|
||
// set the new text.
|
||
if (undoWhat==peUndoStyleAndPara)
|
||
err = noErr;
|
||
else
|
||
{
|
||
select = !(*PeteExtra(pte))->undoInsertion;
|
||
err = PETEInsertUndo(PETE,pte,start,stop,undoWhat,select);
|
||
}
|
||
|
||
// and recalc
|
||
PeteCalcOn(pte);
|
||
|
||
UpdateMyWindow(GetMyWindowWindowPtr((*PeteExtra(pte))->win));
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteKillUndo - destroy undo
|
||
**********************************************************************/
|
||
OSErr PeteKillUndo(PETEHandle pte)
|
||
{
|
||
PETEAllowUndo(PETE,pte,True,True);
|
||
PETEClearUndo(PETE,pte);
|
||
PeteCalcOn(pte);
|
||
return(noErr);
|
||
}
|
||
|
||
#ifndef NEVER
|
||
OSErr RegisterEudoraComponentDir(FSSpecPtr spec);
|
||
OSErr RegisterEudoraComponentFiles(void);
|
||
|
||
#ifndef PETEINLINE
|
||
OSErr PETEInit(PETEInst *pi)
|
||
{
|
||
Component aComponent=0;
|
||
ComponentDescription looking;
|
||
OSErr errCode;
|
||
OSErr shortVers;
|
||
PETEInst maybeI = 0;
|
||
Boolean badVers = False;
|
||
|
||
looking.componentType = 'Edit';
|
||
looking.componentSubType = 'Pete';
|
||
looking.componentManufacturer = 'CSOm';
|
||
|
||
looking.componentFlags = 0L;
|
||
looking.componentFlagsMask = 0L;
|
||
if (aComponent = FindNextComponent(aComponent, &looking))
|
||
{
|
||
if (maybeI=OpenComponent(aComponent))
|
||
{
|
||
shortVers = GetComponentVersion(maybeI)>>16;
|
||
if (shortVers!=(kPETECurrentVersion>>16))
|
||
{
|
||
CloseComponent(maybeI);
|
||
UnregisterComponent(aComponent);
|
||
badVers = True;
|
||
}
|
||
else
|
||
*pi = maybeI;
|
||
}
|
||
else UnregisterComponent(aComponent);
|
||
}
|
||
|
||
if(aComponent == 0L) {
|
||
errCode = badVers ? afpBadVersNum : invalidComponentID;
|
||
ErrorReturn :
|
||
*pi = nil;
|
||
return errCode;
|
||
}
|
||
|
||
return (*pi == nil) ? invalidComponentID : noErr;
|
||
}
|
||
#endif
|
||
|
||
OSErr RegisterEudoraComponentFiles(void)
|
||
{
|
||
FSSpec spec;
|
||
OSErr err;
|
||
Str63 name;
|
||
FSSpec appSpec;
|
||
|
||
/*
|
||
* Eudora
|
||
*/
|
||
RegisterComponentResourceFile(AppResFile,registerComponentGlobal);
|
||
|
||
/*
|
||
* in folder with Eudora
|
||
*/
|
||
if (!(err=GetFileByRef(AppResFile,&spec)))
|
||
{
|
||
appSpec = spec;
|
||
RegisterEudoraComponentDir(&spec);
|
||
if (!FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,STUFF_FOLDER),&spec))
|
||
{
|
||
IsAlias(&spec,&spec);
|
||
spec.parID = SpecDirId(&spec);
|
||
*spec.name = 0;
|
||
RegisterEudoraComponentDir(&spec);
|
||
}
|
||
|
||
/*
|
||
* if we're packaged, in plugins folder up and over
|
||
*/
|
||
if (!(err=ParentSpec(&appSpec,&spec)))
|
||
if (!(err=FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,PACKAGE_MACOS_FOLDER),&spec)))
|
||
if (!(err=FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,PACKAGE_PLUGINS_FOLDER),&spec)))
|
||
{
|
||
IsAlias(&spec,&spec);
|
||
spec.parID = SpecDirId(&spec);
|
||
*spec.name = 0;
|
||
RegisterEudoraComponentDir(&spec);
|
||
}
|
||
|
||
|
||
/*
|
||
* various application support folders/Eudora
|
||
*/
|
||
{
|
||
long domains[]={kUserDomain,kLocalDomain,kSystemDomain,kNetworkDomain};
|
||
FSSpec oldSpec;
|
||
short n = sizeof(domains)/sizeof(domains[0]);
|
||
|
||
Zero(oldSpec);
|
||
while (n-->0)
|
||
if (!FindSubFolderSpec(domains[n],kApplicationSupportFolderType,EUDORA_EUDORA,false,&spec))
|
||
if (!SameSpec(&spec,&oldSpec))
|
||
{
|
||
oldSpec = spec;
|
||
if (!SubFolderSpecOf(&spec,PACKAGE_PLUGINS_FOLDER,false,&spec))
|
||
RegisterEudoraComponentDir(&spec);
|
||
}
|
||
}
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
OSErr RegisterEudoraComponentDir(FSSpecPtr spec)
|
||
{
|
||
CInfoPBRec hfi;
|
||
Str31 name;
|
||
short refN;
|
||
short lastRefN = CurResFile();
|
||
OSErr err=fnfErr;
|
||
FSSpec newSpec;
|
||
short oldResF = CurResFile();
|
||
|
||
hfi.hFileInfo.ioNamePtr = name;
|
||
hfi.hFileInfo.ioFDirIndex = 0;
|
||
while(!DirIterate(spec->vRefNum,spec->parID,&hfi))
|
||
if (hfi.hFileInfo.ioFlFndrInfo.fdType=='thng' &&
|
||
!(err = FSMakeFSSpec(spec->vRefNum,spec->parID, name, &newSpec)))
|
||
{
|
||
IsAlias(&newSpec,&newSpec);
|
||
refN = FSpOpenResFile(&newSpec, fsRdPerm);
|
||
if(refN == -1) {
|
||
if((err = ResError()) == noErr) {
|
||
err = ioErr;
|
||
}
|
||
} else {
|
||
if(RegisterComponentResourceFile(refN,registerComponentGlobal) < 0L) {
|
||
err = resNotFound;
|
||
}
|
||
CloseResFile(refN);
|
||
}
|
||
}
|
||
UseResFile (oldResF);
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PETECleanup - destroy a component
|
||
**********************************************************************/
|
||
#ifndef PETEINLINE
|
||
OSErr PETECleanup(PETEInst instance)
|
||
{
|
||
ComponentDescription info;
|
||
Component comp=nil;
|
||
|
||
if (!GetComponentInfo((Component)instance,&info,nil,nil,nil))
|
||
while (comp = FindNextComponent(comp, &info))
|
||
{
|
||
CloseComponent(instance);
|
||
UnregisterComponent(comp);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/************************************************************************
|
||
* PeteGetTextStyleScrap - Build a stupid bitfield
|
||
************************************************************************/
|
||
OSErr PeteGetTextStyleScrap(PETEHandle pte,long from, long to, Handle *text, PETEStyleListHandle *pslh, PETEParaScrapHandle *pScrap)
|
||
{
|
||
PETEGetStyleScrapFlags itsAllTrueIDontKnowWhyIHaveToBother;
|
||
|
||
itsAllTrueIDontKnowWhyIHaveToBother.allParas = true;
|
||
itsAllTrueIDontKnowWhyIHaveToBother.textTempPref = true;
|
||
itsAllTrueIDontKnowWhyIHaveToBother.styleTempPref = true;
|
||
itsAllTrueIDontKnowWhyIHaveToBother.paraTempPref = true;
|
||
itsAllTrueIDontKnowWhyIHaveToBother.clearLock = true;
|
||
return(PETEGetTextStyleScrap(PETE,pte,from,to,text,pslh,pScrap,&itsAllTrueIDontKnowWhyIHaveToBother));
|
||
}
|
||
|
||
|
||
/***********************************************************************************
|
||
/* LightQuote - quote a selection of text, converting excerpts to plain ">" quotes.
|
||
/* Also reset the quotelevel of each paragraph to 0 so excerpt bars aren't drawn.
|
||
/***********************************************************************************/
|
||
OSErr LightQuote(PETEHandle pte, long startingFrom, long upTo, long *newStart, long *newStop)
|
||
{
|
||
OSErr err = noErr;
|
||
long from = 0, to = 0;
|
||
long start = 0, stop = 0, oStop = 0;
|
||
short i = 0, level = 0;
|
||
PETEParaInfo pinfo;
|
||
Boolean flowed = UseFlowOut;
|
||
|
||
Zero(pinfo);
|
||
|
||
PeteEnsureBreak(pte, startingFrom);
|
||
|
||
//Loop through the selection paragraph by paragraph
|
||
while ((startingFrom < upTo) && (err == noErr))
|
||
{
|
||
from = PeteParaAt(pte,startingFrom);
|
||
|
||
if (!(err = PETEGetParaInfo(PETE,pte,from,&pinfo)))
|
||
{
|
||
start = pinfo.paraOffset;
|
||
if (newStart) {*newStart = start; newStart = nil;}
|
||
stop = (pinfo.paraOffset + pinfo.paraLength > upTo)?upTo:pinfo.paraOffset + pinfo.paraLength;
|
||
oStop = stop;
|
||
level = pinfo.quoteLevel;
|
||
|
||
//Space-stuff leading >'s
|
||
if (flowed && PeteCharAt(pte,start)=='>')
|
||
{
|
||
PeteInsertChar(pte,start,' ',nil);
|
||
oStop++; stop++; upTo++;
|
||
}
|
||
|
||
//Set the quotelevel to 0 so bars aren't drawn
|
||
pinfo.quoteLevel = 0;
|
||
err = PETESetParaInfo(PETE,pte,from,&pinfo,peQuoteLevelValid);
|
||
|
||
//Quote it with a ">" as many times as the quoteLevel dictates
|
||
for (i=0;i<level;i++)
|
||
QuoteLines(pte,start-1,stop,UseFlowOutExcerpt ? FLOWED_QUOTE:QUOTE_PREFIX,&stop);
|
||
|
||
//Move on to next paragraph
|
||
startingFrom = stop;
|
||
upTo += stop - oStop;
|
||
if (newStop) *newStop = start + pinfo.paraLength + stop - oStop;
|
||
}
|
||
}
|
||
|
||
return (err);
|
||
}
|
||
|
||
|
||
/***********************************************************************************
|
||
/* ConvertExcerpt - Convert any excerpts to plain old ordinary quotes in the selection
|
||
/***********************************************************************************/
|
||
OSErr ConvertExcerpt(PETEHandle pte,long startingFrom,long upTo,long *newStart,long *newStop)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
short level = 0;
|
||
long fromPara,toPara;
|
||
long start,stop;
|
||
short i = 0;
|
||
PETEParaInfo pinfo;
|
||
|
||
Zero(pinfo);
|
||
|
||
fromPara = PeteParaAt(pte,startingFrom);
|
||
toPara = PeteParaAt(pte,upTo-1);
|
||
|
||
//Loop through all the paragraphs from start to stop
|
||
for (i=fromPara;i<=toPara;i++)
|
||
{
|
||
if (!(err = PETEGetParaInfo(PETE,pte,i,&pinfo)))
|
||
{
|
||
//If we find an excerpt,
|
||
if (level = pinfo.quoteLevel)
|
||
{
|
||
start = pinfo.paraOffset;
|
||
stop = start + pinfo.paraLength;
|
||
|
||
LightQuote(pte,start,stop,i==fromPara?newStart:nil,i==toPara?newStop:nil);
|
||
}
|
||
else
|
||
{
|
||
if (i==fromPara && newStart) *newStart = pinfo.paraOffset;
|
||
else if (i==toPara && newStop) *newStop = pinfo.paraOffset+pinfo.paraLength;
|
||
}
|
||
}
|
||
}
|
||
|
||
return (err);
|
||
}
|
||
|
||
/************************************************************************
|
||
* PeteQuoteScan - scan a single region for quotes and color them
|
||
************************************************************************/
|
||
void PeteQuoteScan(PETEHandle pte)
|
||
{
|
||
long l1, l2;
|
||
Handle text;
|
||
Boolean peteDirtyWas = PeteIsDirty(pte)!=0;
|
||
Boolean winDirtyWas = (*PeteExtra(pte))->win->isDirty;
|
||
Ptr spot, end;
|
||
long len;
|
||
Str15 quote;
|
||
Boolean is=false;
|
||
PETEParaInfo info;
|
||
|
||
len = PETEGetTextLen(PETE,pte);
|
||
if ((*PeteExtra(pte))->quoteScanned>=len)
|
||
{
|
||
(*PeteExtra(pte))->quoteScanned = -1;
|
||
return;
|
||
}
|
||
|
||
PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
spot = *text + (*PeteExtra(pte))->quoteScanned;
|
||
end = *text+len;
|
||
|
||
// find the first return
|
||
if (!(*PeteExtra(pte))->quoteScanned)
|
||
l1 = 0;
|
||
else
|
||
{
|
||
for (;spot<end;spot++) if (*spot=='\015') break;
|
||
l1 = spot-*text+1;
|
||
}
|
||
|
||
// find the next return
|
||
for (spot++;spot<end;spot++) if (*spot=='\015') break;
|
||
l2 = spot-*text;
|
||
|
||
// Got a line?
|
||
if (l1<=l2 && l1<len) (*PeteExtra(pte))->quoteScanned = l2;
|
||
else {(*PeteExtra(pte))->quoteScanned = -1 ; return;}
|
||
|
||
// excerpted?
|
||
Zero(info);
|
||
if (!PETEGetParaInfo(PETE,pte,PeteParaAt(pte,l1),&info))
|
||
if (info.quoteLevel) is = true;
|
||
|
||
// Great. Grab the quote chars
|
||
if (is || *GetRString(quote,QUOTE_PREFIX))
|
||
{
|
||
if (!is) is = quote[1]==(*text)[l1];
|
||
|
||
NoScannerResets++; // these changes don't count
|
||
|
||
if (is)
|
||
#ifdef WINTERTREE
|
||
if (HasFeature (featureSpellChecking))
|
||
PeteLabel(pte,l1,l2,pQuoteLabel,pQuoteLabel|pSpellLabel);
|
||
else
|
||
PeteLabel(pte,l1,l2,pQuoteLabel,pQuoteLabel);
|
||
#else
|
||
PeteLabel(pte,l1,l2,pQuoteLabel,pQuoteLabel);
|
||
#endif
|
||
else
|
||
PeteNoLabel(pte,l1,l2,pQuoteLabel);
|
||
|
||
NoScannerResets--;
|
||
|
||
if (!peteDirtyWas) PETEMarkDocDirty(PETE,pte,False);
|
||
(*PeteExtra(pte))->win->isDirty = winDirtyWas;
|
||
}
|
||
else (*PeteExtra(pte))->quoteScanned = -1;
|
||
}
|
||
|
||
#pragma segment Main
|
||
/************************************************************************
|
||
* QuoteScan - scan msgs for quotes and if found style
|
||
************************************************************************/
|
||
void QuoteScan(void)
|
||
{
|
||
WindowPtr winWP;
|
||
MyWindowPtr win;
|
||
PETEHandle pte;
|
||
|
||
if (!AmQuoteScanning()) return;
|
||
|
||
for (winWP=FrontWindow_();winWP;winWP=GetNextWindow(winWP))
|
||
{
|
||
if (IsKnownWindowMyWindow(winWP))
|
||
{
|
||
win = GetWindowMyWindowPtr (winWP);
|
||
for (pte=win->pteList;pte;pte=PeteNext(pte))
|
||
{
|
||
while ((*PeteExtra(pte))->quoteScanned >= 0)
|
||
{
|
||
UsingWindow(winWP);
|
||
PeteQuoteScan(pte);
|
||
if (NEED_YIELD) return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* AmQuoteScanning - we're scanning for quotes
|
||
**********************************************************************/
|
||
Boolean AmQuoteScanning(void)
|
||
{
|
||
//quote scanner needed for speller // RGBColor color;
|
||
//quote scanner needed for speller // Str255 title;
|
||
|
||
//quote scanner needed for speller // if (Black(GetRColor(&color,QUOTE_COLOR))) return(false);
|
||
//quote scanner needed for speller // if (!*GetRString(title,QUOTE_PREFIX)) return(false);
|
||
return(true);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteBusy - Pete is busy
|
||
**********************************************************************/
|
||
pascal OSErr PeteBusy(void)
|
||
{
|
||
gEnterWheelHandlerCount++; // this will lock out any scroll wheel c*&$
|
||
#ifdef DEBUG
|
||
if (BUG1) {PushGWorld();WNE(0,nil,0);PopGWorld();}
|
||
#endif
|
||
MemCanFail = False;
|
||
if ((TickCount()-MainEvent.when)>120 && !StillDown())
|
||
{
|
||
PushGWorld();
|
||
CycleBalls();
|
||
PopGWorld();
|
||
}
|
||
else if (NEED_YIELD) WNE(0,nil,0);
|
||
MemCanFail = True;
|
||
gEnterWheelHandlerCount--; // reenable scroll wheels
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteCancelOnEvents - Pete is busy, but cancel if user clicks or types
|
||
**********************************************************************/
|
||
pascal OSErr PeteCancelOnEvents(void)
|
||
{
|
||
static ticks;
|
||
EventRecord event;
|
||
|
||
if (TickCount()-ticks>6)
|
||
{
|
||
ticks = TickCount();
|
||
if (!InBG && OSEventAvail(mDownMask|keyDownMask,&event)) return(userCanceledErr);
|
||
}
|
||
return(PeteBusy());
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PeteTrimTrailingReturns - Remove trailing returns
|
||
**********************************************************************/
|
||
OSErr PeteTrimTrailingReturns(PETEHandle pte,Boolean leaveOne)
|
||
{
|
||
UHandle text;
|
||
uLong size = PeteLen(pte);
|
||
uLong leave;
|
||
OSErr err = PeteGetTextAndSelection(pte,&text,nil,nil);
|
||
|
||
if(err) return err;
|
||
if (size && (*text)[size-1]=='\015')
|
||
{
|
||
leave = size-1;
|
||
while (leave && (*text)[leave]=='\015') leave--;
|
||
if (leaveOne) leave++;
|
||
leave++;
|
||
if (leave<size)
|
||
{
|
||
PETEDocInfo info;
|
||
long index;
|
||
|
||
err = PETEGetDocInfo(PETE,pte,&info);
|
||
if(err) return err;
|
||
|
||
err = PETEGetParaIndex(PETE,pte,leave,&index);
|
||
|
||
while(++index < info.paraCount)
|
||
{
|
||
err = PETEDeletePara(PETE,pte,index);
|
||
if(err) return err;
|
||
}
|
||
|
||
size = PeteLen(pte);
|
||
if(leave<size) err = PeteDelete(pte,leave,size);
|
||
}
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
|
||
OSErr PeteExpandAliases (PETEHandle pte, BinAddrHandle *expandedAddresses, BinAddrHandle originalAddresses, short depth, Boolean wantComments)
|
||
|
||
{
|
||
if (HasFeature (featureNicknameWatching))
|
||
NicknameCachingScan (pte, originalAddresses);
|
||
return (ExpandAliases (expandedAddresses, originalAddresses, depth, wantComments));
|
||
}
|
||
|
||
|
||
#include "editor.h"
|
||
#endif
|