/* 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<=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<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<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<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 (offsetstop) 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<psStyle.textStyle = pse.psStyle.textStyle; /* * get hold of the text */ PETEGetRawText(PETE,fromPTE,&text); /* * copy the style runs one at a time */ while (fromFrompsStartChar = 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;run0) { PCopy(s,"\p Ò"); 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,'É'); MakePStr(s2,*text+pinfo.paraOffset+(*pslh)[run].psStartChar+runLen-31,31); EscapeInHex(s2,s2); PSCat(s,s2); } PCat(s,"\pÓ"); 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= PETEGetTextLen(PETE,pte); long len = PeteLen(pte); PeteGetTextAndSelection(pte,&text,nil,nil); pinfo.tabHandle = nil; if (end1) { 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(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<=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;iwin->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 (;spotquoteScanned = 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