Blame | Last modification | View Log | Download | RSS feed
/*************************************************************************************************RWindow.cby wing kwong (Tiki), WAN 3/2/99************************************************************************************************DescriptionThis file is based on the WASTE and WASTE demo, I had do some modification to make it functionas the way R want.In here, we will handle most of the things related to Window, the otherroutine which is related to Graphic Window may be appear in another file called "RGWindow".The R Programme will create four different kinds of window in this moment, they are Console,Edit, Help and Graphic Window.Console Window : It is a Edit Window with a lot of functionality. You can only have one consolewindow, when the Console window closed, the application closed. You can't remain theapplication open without the console window. This is very important, cause there havea huge part of program is based on this assumption.Edit Window : A Sample Edit window, it based on the WASTE DEMO.Graphic Window : It is related to GRWindow files. It is used for drawing.Help Window : Exactly like Edit Window. except I disable some of the functions.************************************************************************************************Notes:In here, we need to pay attention how WASTE create a window. If you using another methods tocreate another kind of window, you better create another event handlers for those window. Allthe thing like windowPtr, DocumentHandle and WE instance is highly related. If you using somestandard methods to create another kind of winodw. They will probably generate linking error whenthey handling the events implement in here.************************************************************************************************Description of WASTE and WASTE Demo :??? Is it necessary in here ??? I think we needWASTE Demo Project:Controls with Long ValuesCopyright © 1993-1998 Marco PiovanelliAll Rights ReservedC port by John C. Daub*************************************************************************************************//* ************************************************************************************************ *//* INCLUDE HEADER FILE *//* ************************************************************************************************ */#ifndef __ALIASES__#include <Aliases.h>#endif#ifndef __ERRORS__#include <Errors.h>#endif#ifndef __FIXMATH__#include <FixMath.h>#endif#ifndef __TOOLUTILS__#include <ToolUtils.h>#endif#ifndef __FILETYPESANDCREATORS__#include <FileTypesAndCreators.h>#endif/*#ifndef _LongCoords_#include "LongCoords.h"#endif*/#ifndef __WEDEMOAPP__#include "RIntf.h"#endif#ifndef __SMARTSCROLLAPI__#include "SmartScroll.h"#endif#include "WETabs.h"#include "WETabHooks.h"#include "Defn.h"#include "Graphics.h"#include <R_ext/Boolean.h>/* ************************************************************************************************ *//* Define Constant *//* ************************************************************************************************ */#define eGWin 11/* ************************************************************************************************Constant, Global variables and prototype************************************************************************************************ */Ptr gPreAllocatePointer;Boolean Have_Console = false;WindowPtr Console_Window;WindowPtr Working_Window;SInt16 Edit_Window = 1;WindowPtr Graphic_Window[MAX_NUM_G_WIN + 1];WindowPtr Edit_Windows[MAX_NUM_E_WIN + 1];SInt16 Current_Window =1;SInt32 Num_Of_Window =1;SInt16 Edit_Number = 0;extern Graphic_Ref gGReference[MAX_NUM_G_WIN + 1];extern gtabSize;extern SInt16 Help_Window, gTextSize;extern WindowPtr Help_Windows[MAX_NUM_H_WIN + 1];// some consts used by DoGrow()static void hideTextRect(Rect*);static SInt32 sScrollStep; // how many pixels to scroll (used by ScrollProc)extern void SetTab(void);extern int R_SetOptionWidth(int w);void RnWWin(char* buf, SInt16 len, WEReference we );enum {kMinWindowWidth = 200,kMinWindowHeight = 80};/* ************************************************************************************************CalcGrowIconRect************************************************************************************************ */static void CalcGrowIconRect( WindowPtr window, Rect *iconRect ){Rect portRect = window -> portRect ;iconRect->top = portRect.bottom - (kBarWidth - 2);iconRect->left = portRect.right - (kBarWidth - 2);iconRect->bottom = portRect.bottom;iconRect->right = portRect.right;}/* ************************************************************************************************CalcTextRect************************************************************************************************ */static void CalcTextRect( WindowPtr window, Rect *textRect ){Rect portRect = window -> portRect ;textRect->top = 0;textRect->left = 0;textRect->bottom = portRect.bottom - (kBarWidth - 1);textRect->right = portRect.right - (kBarWidth - 1);InsetRect( textRect, kTextMargin, kTextMargin );}/* ************************************************************************************************CalcTextRect************************************************************************************************ */static void CalcBigTextRect( WindowPtr window, Rect *textRect ){Rect portRect = window -> portRect ;textRect->top = 0;textRect->left = 0;textRect->bottom = portRect.bottom - (kBarWidth - 1);textRect->right = 2000;InsetRect( textRect, kTextMargin, kTextMargin );}/* ************************************************************************************************CalcScrollBarRect************************************************************************************************ */static void CalcScrollBarRect( WindowPtr window, Orientation orientation, Rect *barRect ){Rect portRect = window -> portRect ;switch ( orientation ){case kVertical :{barRect->top = -1;barRect->left = portRect.right - (kBarWidth - 1);barRect->bottom = portRect.bottom - (kBarWidth - 2);barRect->right = portRect.right + 1;break;}case kHorizontal :{barRect->top = portRect.bottom - (kBarWidth - 1);barRect->left = -1;barRect->bottom = portRect.bottom + 1;barRect->right = portRect.right - (kBarWidth - 2 );break;}}}/* ************************************************************************************************the standard Toolbox trap _DrawGrowIcon draws two lines from the grow iconto the left and top margins of the window's content areathese additional lines may create ugly dirt, so we use this routine to temporarilyset the clip region to the grow icon rect.in addition, if validate is true, we call _ValidRect on the icon rect************************************************************************************************ */static void MyDrawGrowIcon( WindowPtr window, Boolean validate ){GrafPtr savePort;RgnHandle saveClip;Rect r;// save port and set thePort to windGetPort( &savePort );SetPort( window );// save the clip regionsaveClip = NewRgn();GetClip( saveClip );// calculate the grow icon rectCalcGrowIconRect( window, &r );// set clip region to grow icon rectClipRect( &r );// call _DrawGrowIconDrawGrowIcon( window );// if validate is true, remove the grow icon rect from the update regionif ( validate )ValidRect( &r );// restore old clip regionSetClip( saveClip );DisposeRgn( saveClip );// restore old portSetPort( savePort );}/* ************************************************************************************************ScrollBarChanged************************************************************************************************ */static void ScrollBarChanged( WindowPtr window ){// scroll text to reflect new scroll bar settingDocumentHandle hDocument = GetWindowDocument( window );WEReference we;LongRect viewRect, destRect;we = (*hDocument)->we;WEGetViewRect( &viewRect, we );WEGetDestRect( &destRect, we );WEScroll(viewRect.left - destRect.left - LCGetValue( (*hDocument)->scrollBars[ kHorizontal ] ),viewRect.top - destRect.top - LCGetValue( (*hDocument)->scrollBars[ kVertical ] ),we);}/* ************************************************************************************************AdjustBars************************************************************************************************ */static void AdjustBars ( WindowPtr window ){DocumentHandle hDocument ;WEReference we ;GrafPtr savePort ;LongRect viewRect, destRect ;SInt32 visible, total, value, max ;ControlHandle bar ;GetPort ( & savePort ) ;SetPort ( window ) ;hDocument = GetWindowDocument ( window ) ;we = ( * hDocument ) -> we ;// get the view and destination rectangleWEGetViewRect ( & viewRect, we ) ;WEGetDestRect ( & destRect, we ) ;// do the vertical axis// get scroll bar handlebar = ( * hDocument ) -> scrollBars [ kVertical ] ;// calculate new scroll bar settings// NOTE: (destRect.bottom - destRect.top) always equals the total text height because// WASTE automatically updates destRect.bottom whenever line breaks are recalculatedtotal = destRect . bottom - destRect . top ; // total pixel heightvisible = viewRect . bottom - viewRect . top ; // visible pixel heightmax = total - visible ; // scrollable range (in pixels)value = viewRect . top - destRect . top ; // thumb location within scrollable range// make sure max is always non-negativeif ( max <= 0 ) max = 0 ;// notify SmartScrollSetSmartScrollInfo ( bar, visible, total ) ;// reset the scroll barLCSetMax ( bar, max ) ;LCSetValue ( bar, value ) ;// if value exceeds max then the bottom of the destRect is above// the bottom of the view rectangle: we need to scroll the text downwardif ( value > max ){ScrollBarChanged ( window ) ;}// now do the horizontal axis// get scroll bar handlebar = ( * hDocument ) -> scrollBars [ kHorizontal ] ;// calculate new scroll bar settingstotal = destRect . right - destRect . left ; // total pixel widthvisible = viewRect . right - viewRect . left ; // visible pixel widthmax = total - visible ; // scrollable range (in pixels)value = viewRect . left - destRect . left ; // thumb location within scrollable range// make sure max is always non-negativeif ( max <= 0 ) max = 0 ;// notify SmartScrollSetSmartScrollInfo ( bar, visible, total ) ;// reset the scroll barLCSetMax ( bar, max ) ;LCSetValue ( bar, value ) ;SetPort ( savePort ) ;}/* ************************************************************************************************ViewChanged************************************************************************************************ */static void ViewChanged( WindowPtr window ){DocumentHandle hDocument;GrafPtr savePort;ControlHandle bar;Rect r;LongRect viewRect;Orientation orientation;GetPort( &savePort );SetPort( window );hDocument = GetWindowDocument( window );// resize the text areaCalcTextRect( window, &r );WERectToLongRect( &r, &viewRect );WESetViewRect( &viewRect, (*hDocument)->we );// move and resize the control barsfor ( orientation = kVertical; orientation <= kHorizontal; orientation++ ){bar = (*hDocument)->scrollBars[ orientation ];CalcScrollBarRect( window, orientation, &r );MoveControl( bar, r.left, r.top );SizeControl( bar, r.right - r.left, r.bottom - r.top );ValidRect( &r );}// reset the thumb positions and the max values of the control barsAdjustBars( window );// redraw the control barsShowControl( (*hDocument)->scrollBars[ kVertical ] );ShowControl( (*hDocument)->scrollBars[ kHorizontal ] );SetPort( savePort );}/* ************************************************************************************************This is a deviation from the original Pascal WASTE Demo App code.This "morally correct" code for window dragging is per an article in MacTechMagazine (July 1994, Vol 10, No. 7). by Eric Shapiro (of Rock Ridge Enterprises)called "Multiple Monitors vs. Your Application"Eric addressed numerous things to allow your app to deal nicely with multiplemonitor setups, one of them is dragging.According to Eric, many apps don't let you drag windows to second monitors, andthough holding down the cmd/opt keys often overrides this problem, it shouldstill be updated. And the only reason qd.screenBits.bounds works to allowyou to drag to second monitors is because of a kludge Apple put in the Window ManagerSo, this is some code from Eric to make our app be "morally correct" :)************************************************************************************************ */void DoDrag ( Point thePoint, WindowPtr window ){Rect desktopBounds ;if ( gHasColorQD ){desktopBounds = ( * GetGrayRgn ( ) ) -> rgnBBox ;}else{desktopBounds = qd . screenBits . bounds ;}DragWindow ( window, thePoint, & desktopBounds ) ;}/* ************************************************************************************************Resize : when you resize a graphic window, you need to redraw the content.************************************************************************************************ */void Resize ( Point newSize, WindowPtr window ){DocumentHandle hDocument ;GrafPtr savePort ;Rect r ;RgnHandle tempRgn, dirtyRgn ;// set up the portGetPort( & savePort ) ;SetPort ( window ) ;hDocument = GetWindowDocument ( window ) ;// create temporary regions for calculationstempRgn = NewRgn ( ) ;dirtyRgn = NewRgn ( ) ;GraResize(window);// save old text regionCalcTextRect ( window, & r ) ;RectRgn ( tempRgn, & r ) ;// erase the old grow icon rectCalcGrowIconRect ( window, & r ) ;EraseRect ( & r ) ;// hide the scroll barsHideControl ( ( * hDocument ) -> scrollBars [ kVertical ] ) ;HideControl ( ( * hDocument ) -> scrollBars [ kHorizontal ] ) ;// perform the actual resizing of the window, redraw scroll bars and grow iconSizeWindow ( window, newSize . h, newSize . v, false ) ;if ((window == Console_Window) || (isEditWindow(window) != 0) || (isHelpWindow(window) != 0))ViewChanged ( window ) ;MyDrawGrowIcon ( window, true ) ;// calculate the dirty region (to be updated)CalcTextRect ( window, & r );RectRgn ( dirtyRgn, & r ) ;XorRgn ( dirtyRgn, tempRgn, dirtyRgn ) ;InsetRect ( & r, - kTextMargin, - kTextMargin ) ;RectRgn ( tempRgn, & r ) ;SectRgn ( dirtyRgn, tempRgn, dirtyRgn ) ;// mark the dirty region as invalidInvalRgn ( dirtyRgn ) ;// throw away temporary regionsDisposeRgn ( tempRgn ) ;DisposeRgn ( dirtyRgn ) ;// restore the portSetPort ( savePort ) ;}/* ************************************************************************************************DoGrow:***************************************************************************************************When the console window grow, you need to reset the option width. Unfortunately, the functionCharWidth didn't doing the thing we expected. We need to multiple a constant 0.75 (by experiment)to get the best effect.************************************************************************************************ */void DoGrow ( Point hitPt, WindowPtr window ){Rect sizeRect ;SInt32 newSize ;WEReference we;SInt16 Console_Width, NumofChar;GrafPtr savePort;WEStyleMode mode;TextStyle ts;SetRect( & sizeRect, kMinWindowWidth, kMinWindowHeight, SHRT_MAX, SHRT_MAX ) ;if ( ( newSize = GrowWindow ( window, hitPt, & sizeRect ) ) != 0L ){// for some reason, GrowWindow( ) returns a long value,// but it's really a PointResize ( * ( Point * ) & newSize, window ) ;if (window == Console_Window){Console_Width = (Console_Window ->portRect).right - (Console_Window ->portRect).left ;GetPort(&savePort);SetPort(Console_Window);TextFont(4);TextSize(gTextSize);NumofChar = (int)(((Console_Width - 15) / CharWidth('M')) - 0.5) ;R_SetOptionWidth(NumofChar);SetPort(savePort);}}}/* ************************************************************************************************DoZoom************************************************************************************************ */void DoZoom ( SInt16 partCode, WindowPtr window ){DocumentHandle hDocument;GrafPtr savePort;Rect r;GetPort( &savePort );SetPort( window );hDocument = GetWindowDocument(window);r = window -> portRect ;EraseRect( &r );HideControl( (*hDocument)->scrollBars[ kVertical ] );HideControl( (*hDocument)->scrollBars[ kHorizontal ] );ZoomWindow( window, partCode, false );if ((window == Console_Window) || (isEditWindow(window) != 0))ViewChanged( window );CalcTextRect( window, &r );InvalRect( &r );SetPort( savePort );}/* ************************************************************************************************ScrollProc: this is a callback tourine called by the Toolbox Control Manager move the scroll barthumb and scroll the text accordingly************************************************************************************************ */static pascal void ScrollProc ( ControlHandle bar, ControlPartCode partCode ){SInt32 value, step ;if ( partCode == kControlNoPart ){return ;}value = LCGetValue ( bar ) ;step = sScrollStep ;if ( ( ( value < LCGetMax ( bar ) ) && ( step > 0 ) ) ||( ( value > 0 ) && ( step < 0 ) ) ){LCSetValue ( bar, value + step ) ;ScrollBarChanged ( FrontWindow ( ) ) ;}}/* ************************************************************************************************MySendControlMessage************************************************************************************************ */static SInt32 MySendControlMessage ( ControlHandle inControl, SInt16 inMessage, SInt32 inParam ){GrafPtr savePort ;Handle cdef ;SInt32 result ;SInt8 saveState ;// get a handle to the control definition procedurecdef = ( * inControl ) -> contrlDefProc ;// make sure the CDEF is loadedif ( * cdef == nil ){LoadResource ( cdef ) ;if ( * cdef == nil ){return 0 ; // emergency exit (couldn't load CDEF)}}// lock it downsaveState = HGetState ( cdef ) ;HLock ( cdef ) ;// set up the portGetPort ( & savePort ) ;SetPort ( ( * inControl ) -> contrlOwner ) ;// call the CDEFresult = CallControlDefProc ( ( ControlDefUPP ) StripAddress ( * cdef ),GetControlVariant ( inControl ), inControl, inMessage, inParam ) ;// unlock the CDEFHSetState ( cdef, saveState ) ;// restore the portSetPort ( savePort ) ;// return result codereturn result ;}/* ************************************************************************************************LiveScroll************************************************************************************************ */static void LiveScroll ( ControlHandle inControl, Point inHitPt, WindowPtr inWindow ){IndicatorDragConstraint constraint ;Point mouseLoc ;SInt32 initialValue, oldValue, curValue, max ;SInt16 scrollRange, delta ;Orientation orientation ;// hilite the control thumb// this does nothing with the standard System 7.x scroll bar, but is required for// correct visual feedback with the Apple Grayscale Appearance (as implemented by// the Appearance control panel in MacOS 8, or by Aaron/Kaleidoscope)HiliteControl ( inControl, kControlIndicatorPart ) ;// get limit & slop rects that should be used for dragging the indicator// (see IM: Mac Toolbox Essentials, page 5-114)* ( Point * ) & constraint . limitRect = inHitPt ;MySendControlMessage ( inControl, thumbCntl, ( SInt32 ) & constraint ) ;// determine the orientation of the scroll barorientation = ( constraint . axis == kVerticalConstraint ) ? kHorizontal : kVertical ;// calculate the area in which the thumb can travelif ( orientation == kVertical ){scrollRange = ( constraint . limitRect . bottom - constraint . limitRect . top ) ;}else{scrollRange = ( constraint . limitRect . right - constraint . limitRect . left ) ;}// get current value & maxinitialValue = oldValue = curValue = LCGetValue ( inControl ) ;max = LCGetMax ( inControl ) ;// mouse tracking loopwhile ( StillDown ( ) ){// get current mouse locationGetMouse ( & mouseLoc ) ;// do nothing if the mouse is outside the slop rectangleif ( PtInRect ( mouseLoc, & constraint . slopRect ) ){// calculate pixel offset relative to initial hit pointif ( orientation == kVertical ){delta = mouseLoc . v - inHitPt . v ;}else{delta = mouseLoc . h - inHitPt . h ;}// calculate new control valuecurValue = initialValue + FixMul ( max, FixRatio ( delta, scrollRange ) ) ;if ( curValue < 0 ) curValue = 0 ;if ( curValue > max ) curValue = max ;}if ( curValue != oldValue ){// set new control valueLCSetValue ( inControl, curValue ) ;ScrollBarChanged ( inWindow ) ;oldValue = curValue ;}}// unhighlight the thumbHiliteControl ( inControl, kControlNoPart ) ;}/* ************************************************************************************************DoScrollBar************************************************************************************************ */static void DoScrollBar ( Point hitPt, EventModifiers modifiers, WindowPtr window ){DocumentHandle hDocument;ControlHandle bar = nil;LongRect viewRect;ControlPartCode partCode;SInt32 pageSize;SInt32 step = 0;#ifdef __cplusplusstatic ControlActionUPP sScrollerUPP = NewControlActionProc( ScrollProc );#elsestatic ControlActionUPP sScrollerUPP = nil;if (sScrollerUPP == nil){sScrollerUPP = NewControlActionProc( ScrollProc );}#endifhDocument = GetWindowDocument( window );WEGetViewRect( &viewRect, (*hDocument)->we );// find out which control was hit (if any) and in which partpartCode = FindControl( hitPt, window, &bar );// if any control was hit, it must be one of our two scroll bars:// find out which and calculate the page size for itif ( bar == (*hDocument)->scrollBars[ kVertical ] ){pageSize = viewRect.bottom - viewRect.top;}else if ( bar == (*hDocument)->scrollBars[ kHorizontal ] ){pageSize = viewRect.right - viewRect.left;}else{return; // return immediately if none of our scrollbars was hit}// dispatch on partCodeswitch ( partCode ){case kControlIndicatorPart:{// click in thumbif ( modifiers & optionKey ){// call TrackControl with no actionProc and adjust textTrackControl ( bar, hitPt, nil ) ;LCSynch ( bar ) ;ScrollBarChanged ( window ) ;}else{LiveScroll ( bar, hitPt, window ) ;}return;}case kControlUpButtonPart:{step = - ( ( modifiers & optionKey ) ? 1 : kScrollDelta ) ;break ;}case kControlDownButtonPart:{step = + ( ( modifiers & optionKey ) ? 1 : kScrollDelta ) ;break ;}case kControlPageUpPart:{step = - ( pageSize - kScrollDelta ) ;break ;}case kControlPageDownPart:{step = + ( pageSize - kScrollDelta ) ;break ;}} // switch// save step in a static variable for our ScrollProc callbacksScrollStep = step ;// track the mouseTrackControl ( bar, hitPt, sScrollerUPP ) ;}/* ************************************************************************************************* TextScrolled** This is a callback routine called whenever the text is scrolled automatically.* Since auto-scrolling is enabled, WEScroll may be invoked internally by WASTE* in many different circumstances, and we want to be notified when this happens* so we can adjust the scroll bars************************************************************************************************ */static pascal void TextScrolled ( WEReference we ){WindowPtr window = nil ;// retrieve the window pointer stored in the WE instance as a "reference constant"if ( WEGetInfo( weRefCon, & window, we ) != noErr ){return ;}// make sure the scroll bars are in synch with the destination rectangleAdjustBars ( window ) ;}/* ************************************************************************************************AddClippingName:************************************************************************************************ */static pascal OSErr AddClippingName ( DragReference drag, WEReference we ){// add a 'clnm' flavor containing the name of the document originating the drag// this flavor is used by the Finder (version 8.0 and later) to determine the// name of the clipping fileWindowPtr window = nil ;Str255 windowTitle ;// retrieve the window pointer stored in the WE instance as a "reference constant"if ( WEGetInfo ( weRefCon, & window, we ) != noErr ){return paramErr ;}// get the window titleGetWTitle ( window, windowTitle ) ;// put the window title into the drag, as a 'clnm' flavor// we add this flavor to the same drag item used by WASTE to add the TEXT// (note that the reference number of this drag item = the WEReference )return AddDragItemFlavor ( drag, ( ItemReference ) we, 'clnm', windowTitle,StrLength ( windowTitle ) + 1, flavorNotSaved ) ;}/* ************************************************************************************************DoContent: This function will be called when you click inside the window************************************************************************************************ */Boolean DoContent ( Point hitPt, const EventRecord * event, WindowPtr window ){WEReference we = GetWindowWE ( window ) ;Rect textRect ;GrafPtr savePort ;Boolean isMyClick = false ;// set up the portGetPort ( & savePort ) ;SetPort ( window ) ;// convert the point to local coordinatesGlobalToLocal ( & hitPt ) ;// a click in an inactive window should normally activate it,// but the availability of the Drag Manager introduces an exception to this rule:// a click in the background selection may start a drag gesture,// without activating the windowif ( IsWindowHilited ( window ) ){isMyClick = true ; // active window -> always handle click}else if ( gHasDragAndDrop ){SInt32 selStart, selEnd ;RgnHandle selRgn ;WEGetSelection ( & selStart, & selEnd, we ) ;selRgn = WEGetHiliteRgn ( selStart, selEnd, we ) ;isMyClick = PtInRgn ( hitPt, selRgn ) && WaitMouseMoved ( event -> where ) ;DisposeRgn ( selRgn ) ;}if ( isMyClick ){CalcTextRect ( window, & textRect ) ;if ( PtInRect ( hitPt, & textRect ) ){WEClick ( hitPt, event -> modifiers, event -> when, we ) ;}else{DoScrollBar ( hitPt, event -> modifiers, window ) ;}}// restore the portSetPort ( savePort ) ;// return true if the click should activate this windowreturn ! isMyClick ;}/* ************************************************************************************************DoScrollKey: Handle Scroll key************************************************************************************************ */static void DoScrollKey ( SInt16 keyCode, WindowPtr window ){DocumentHandle hDocument ;ControlHandle bar ;SInt32 value ;LongRect viewRect ;hDocument = GetWindowDocument ( window ) ;bar = ( * hDocument ) -> scrollBars [ kVertical ] ;// get current scroll bar valuevalue = LCGetValue ( bar ) ;// get text view rectWEGetViewRect ( & viewRect, ( * hDocument ) -> we ) ;switch ( keyCode ){case keyPgUp:{value -= ( viewRect . bottom - viewRect . top ) - kScrollDelta ;break ;}case keyPgDn:{value += ( viewRect . bottom - viewRect . top ) - kScrollDelta ;break ;}case keyHome:{value = 0 ;break ;}case keyEnd:{value = LONG_MAX ;break ;}} // switch// set the new scroll bar value and scroll the text pane accordinglyLCSetValue ( bar, value ) ;ScrollBarChanged ( window ) ;}/* ************************************************************************************************DoKey : handle key event (keyPgUp, keyPgDn, keyHome ...)************************************************************************************************ */void DoKey ( SInt16 key, const EventRecord * event ){WindowPtr window ;SInt16 keyCode ;// do nothing if no window is activeif ( ( window = FrontWindow ( ) ) == nil )return;// extract virtual key code from event recordkeyCode = ( event->message & keyCodeMask ) >> 8 ;// page movement keys are handled by DoScrollKey()switch ( keyCode ){case keyPgUp:case keyPgDn:case keyHome:case keyEnd:{DoScrollKey ( keyCode, window ) ;break ;}default:{WEKey ( key, event -> modifiers, GetWindowWE (window) ) ;break ;}}}/* ************************************************************************************************DoUpdate:***************************************************************************************************Based on WASTE DEMO. However, when you update a graphic window, you need to do something more thanText window.************************************************************************************************ */void DoUpdate ( WindowPtr window ){GrafPtr savePort ;RgnHandle updateRgn ;// if we have no windows, there's nothing to update!if ( window == nil ){return ;}// save the old drawing portGetPort ( & savePort ) ;SetPort ( window ) ;// notify everything that we're doing an update.BeginUpdate ( window ) ;// BeginUpdate sets the window port visRgn to the region to updateupdateRgn = window -> visRgn ;if ( ! EmptyRgn ( updateRgn ) ) // if it's not an empty region, let's update it!{// erase the update regionEraseRgn ( updateRgn ) ;// draw scroll barsUpdateControls ( window, updateRgn ) ;// draw grow iconMyDrawGrowIcon ( window, false ) ;// draw textWEUpdate ( updateRgn, GetWindowWE ( window ) ) ;}// tell everything we're done updatingEndUpdate ( window ) ;if (isGraphicWindow(window)){GraUpdate(window);}// restore the old graphics portSetPort ( savePort ) ;}/* ************************************************************************************************DoActivate :***************************************************************************************************Based on WASTE DEMO. However, when you activate a graphic window, you need to do something morethan Text window.************************************************************************************************ */void DoActivate ( Boolean isActivating, WindowPtr window ){DocumentHandle hDocument ;WEReference we ;GrafPtr savePort ;Rect barRect ;ControlPartCode barHilite ;SInt16 menuID ;Orientation orientation ;// if this is not one of our document windows, nothing to do here...if ( ( hDocument = GetWindowDocument ( window ) ) == nil ){return ;}we = ( * hDocument ) -> we ;// sanity check: do nothing if required activation state// is the same as the current activation stateif ( isActivating == WEIsActive ( we ) ){return ;}// set up the portGetPort ( & savePort ) ;SetPort ( window ) ;// activate or deactivate the text (and any other relevant stuff) depending on just// what we're doing here...if ( isActivating ){WEActivate ( we ) ;barHilite = kControlNoPart ;}else{WEDeactivate ( we ) ;barHilite = kControlDisabledPart ;}// redraw the grow icon (and validate its rect)MyDrawGrowIcon ( window, true ) ;// redraw the scroll bars with the new highlighting (and validate their rects)for ( orientation = kVertical ; orientation <= kHorizontal ; orientation ++ ){HiliteControl ( ( * hDocument ) -> scrollBars [ orientation ], barHilite ) ;CalcScrollBarRect ( window, orientation, & barRect ) ;ValidRect ( & barRect ) ;}// if activating, undim text-related menusif ( isActivating ){for ( menuID = kMenuEdit ; menuID <= kMenuFeatures ; menuID ++ ){EnableItem ( GetMenuHandle ( menuID ), 0 ) ;}}// invalidate the menu barInvalMenuBar ( ) ;// restore the old graphics port..SetPort ( savePort ) ;}/* ************************************************************************************************CreateGraphicWindow***************************************************************************************************This routine is used to create a Graphic window. You need to resize the window as the parameterspecified.************************************************************************************************ */WindowPtr CreateGraphicWindow (int wid, int h){OSErr err;SInt16 WinIndex;Rect theWholeScreen;err = newWindow (nil, 1);if (!err){SizeWindow ( Working_Window, wid, h, false );SetRect(&theWholeScreen, (qd.screenBits).bounds.left +4,qd.screenBits.bounds.top +24, qd.screenBits.bounds.right -4,qd.screenBits.bounds.bottom -4);MoveWindow(Working_Window, theWholeScreen.right - wid - 5, theWholeScreen.top + 20, true);ShowWindow(Working_Window);}else{GWdoErrorAlert(eGWin);}return Working_Window;}/* ************************************************************************************************CreateWindow: Create Text Window************************************************************************************************ */OSErr CreateWindow (const FSSpec * pFileSpec){OSErr err;err = newWindow (pFileSpec, 0);if (!err)ShowWindow(Working_Window);return err;}/* ************************************************************************************************newWindow : General Procedure , which used to create a new window (all kind of windows)************************************************************************************************ */OSErr newWindow ( const FSSpec * pFileSpec, int graphic){DocumentHandle hDocument = nil ;WindowPtr window = nil ;AliasHandle alias = nil ;WEReference we = nil ;ControlHandle bar = nil ;FInfo fileInfo ;Rect textRect, theWholeScreen ;LongRect lr ;Orientation orientation ;OSErr err ;Str255 titledString = "\pUntitled ";Str255 numberAsString;MenuHandle windowsMenu;WEStyleMode mode;TextStyle ts;#if TARGET_API_MAC_CARBONFMFontFamily fontFamily = 0 ;#elseSInt16 fontFamily = 0 ;#endif#ifdef __cplusplusstatic WEScrollUPP sScrollerUPP = NewWEScrollProc ( TextScrolled ) ;static WEPreTrackDragUPP sPreTrackerUPP = NewWEPreTrackDragProc ( AddClippingName ) ;#elsestatic WEScrollUPP sScrollerUPP = nil ;static WEPreTrackDragUPP sPreTrackerUPP = nil ;if ( sScrollerUPP == nil ){sScrollerUPP = NewWEScrollProc ( TextScrolled ) ;sPreTrackerUPP = NewWEPreTrackDragProc ( AddClippingName ) ;}#endif// allocate a relocateable block to hold a document recordhDocument = ( DocumentHandle ) NewHandleClear ( sizeof ( DocumentRecord ) ) ;if ( ( err = MemError( ) ) != noErr ){goto cleanup ;}// create the window from a 'WIND' template: the window is initially invisible// if ColorQuickDraw is available, create a color windowif ( gHasColorQD ){window = GetNewCWindow ( kWindowTemplateID, nil, ( WindowPtr ) -1L ) ;}else{window = GetNewWindow ( kWindowTemplateID, nil, ( WindowPtr ) -1L ) ;}// make sure we got a windowif ( window == nil ){err = memFullErr ;goto cleanup ;}// link the document record to the window and the other way aroundSetWRefCon ( window, ( SInt32 ) hDocument ) ;( * hDocument ) -> owner = window ;// we got a window, so tell QuickDraw where to draw...SetPort ( window ) ;// calculate the text rectangleif (graphic){hideTextRect(&textRect);}elseCalcBigTextRect ( window, & textRect ) ;WERectToLongRect ( & textRect, & lr ) ;// create a new WASTE instanceif ( ( err = WENew ( & lr, & lr, weDoAutoScroll +weDoOutlineHilite +weDoUndo +weDoIntCutAndPaste +weDoDragAndDrop +weDoUseTempMem +weDoDrawOffscreen, & we) ) != noErr ){goto cleanup ;}// save a reference to the window in the WE instanceif ( ( err = WESetInfo ( weRefCon, & window, we ) ) != noErr ){goto cleanup ;}// now the other way around: save the WE reference in the document record( * hDocument ) -> we = we ;// set up our scroll callbackif ( ( err = WESetInfo ( weScrollProc, & sScrollerUPP, we ) ) != noErr ){goto cleanup ;}// set up our pre-TrackDrag callbackif ( ( err = WESetInfo ( wePreTrackDragHook, & sPreTrackerUPP, we ) ) != noErr ){goto cleanup ;}// create the scroll bars from a control templatefor ( orientation = kVertical ; orientation <= kHorizontal; orientation ++ ){if ( ( bar = GetNewControl ( kScrollBarTemplateID, window ) ) == nil ){err = memFullErr ;goto cleanup ;}HiliteControl ( bar, kControlDisabledPart ) ;// attach a LongControl record to the scroll bar: this allows us to use long// settings and thus scroll text taller than 32,767 pixelsif ( ( err = LCAttach ( bar ) ) != noErr ){goto cleanup;}// save control handle in the document record( * hDocument ) -> scrollBars [ orientation ] = bar ;} // for// ViewChanged adjusts the scroll bars rectangles to the window frameif (graphic == 0)ViewChanged ( window ) ;// if pFileSpec is not nil, it points to a file to read, so let's read it!if ( pFileSpec != nil ){// turn the cursor into a wristwatch because this can be a lengthy operationSetCursor ( * GetCursor ( watchCursor ) ) ;// retrieve file infomationif ( ( err = FSpGetFInfo ( pFileSpec, & fileInfo ) ) != noErr ){goto cleanup ;}// make sure we recognize the file typeif ( ( fileInfo . fdType != kTypeText ) && ( fileInfo . fdType != ftSimpleTextDocument ) ){err = badFileFormat ;goto cleanup ;}// read in the fileif ( ( err = ReadTextFile ( pFileSpec, we ) ) != noErr ){goto cleanup ;}// set the window title to the file nameSetWTitle ( window, pFileSpec -> name ) ;// create an alias to keep track of the fileif ( ( err = NewAlias ( nil, pFileSpec, & alias ) ) != noErr ){goto cleanup ;}( * hDocument ) -> fileAlias = ( Handle ) alias ;// if the file is a read-only file, go ahead and enable those flagsif ( fileInfo . fdType == ftSimpleTextDocument ){WEFeatureFlag ( weFReadOnly, weBitSet, we ) ;}// let's make sure the cursor is happy...SetCursor ( & qd . arrow ) ;}// adjust scroll bar settings based on the total text heightif (!graphic)AdjustBars ( window ) ;if (!Have_Console){SetWTitle(window, "\pR Console");Console_Window = window;// If you think that the console window didn't need to have tab function.// You can simply delete these two lines.// Also, if you think that different windows ought to have different tab space.// what you need to do is replicate the following two lines.// and use it into another space.// I use char M to represent the char width of each character.Have_Console = true;}else{if (graphic == 0) {Edit_Windows[Edit_Window] = window;Edit_Window ++;Edit_Number ++;NumToString( Edit_Number ,numberAsString);GWdoConcatPStrings(titledString,numberAsString);SetWTitle(window, titledString);SetTab();SetRect(&theWholeScreen, (qd.screenBits).bounds.left +4,qd.screenBits.bounds.top +24, qd.screenBits.bounds.right -4,qd.screenBits.bounds.bottom -4);MoveWindow(window, theWholeScreen.right - (window->portRect.right + 5), theWholeScreen.top + 20, true);}}if (graphic){NumToString(Num_Of_Window,numberAsString);GWdoConcatPStrings(titledString,numberAsString);SetWTitle(window, titledString);Graphic_Window[Current_Window] = window;New_G_History(Current_Window);Current_Window++;Num_Of_Window++;}Working_Window = window;// finally! show the document windowGetFNum ( "\pmonaco", & ts . tsFont ) ;// use script-preserving mode by default (see WASTE docs)// force font change across the whole selection if the option key was held down/* mod Jago 08/29/00mode = weDoFont ;// set the font of the selectionWESetStyle ( mode, & ts, GetWindowWE ( window ) ) ;*/GetFNum ( "\pmonaco", & fontFamily ) ;WESetOneAttribute ( kCurrentSelection, kCurrentSelection, weTagFontFamily,& fontFamily, sizeof ( fontFamily ), GetWindowWE ( window ) ) ;changeSize(window, gTextSize);cleanup:if ( err != noErr ){ErrorAlert ( err ) ;}return err ;}/* ************************************************************************************************DestroyWindow************************************************************************************************ */void DestroyWindow ( WindowPtr window ){DocumentHandle hDocument;SInt16 menuID ;hDocument = GetWindowDocument ( window ) ;// destroy the WASTE instanceWEDispose ( ( * hDocument ) -> we ) ;// destory the LongControl records attached to the scroll barsLCDetach ( ( * hDocument ) -> scrollBars [ kVertical ] ) ;LCDetach ( ( * hDocument ) -> scrollBars [ kHorizontal ] ) ;// dispose of the file alias, if anyForgetHandle ( & ( ( * hDocument ) -> fileAlias ) ) ;// destroy the window record and all associated data structuresDisposeWindow ( window ) ;// finally, dispose of the document recordDisposeHandle ( ( Handle ) hDocument ) ;// adjust the menus to suitfor ( menuID = kMenuFont ; menuID <= kMenuFeatures ; menuID ++ ){DisableItem ( GetMenuHandle ( menuID ), 0 ) ;}InvalMenuBar ( ) ;}/* ************************************************************************************************hideTextRect:***************************************************************************************************Used in Graphic window, which hide the corresponding TextEdit Field. We hide the TextField insteadof creating another kind of window, because the event processing procedure is based on the WASTEDEMO. Thus, if we have two different kind of window structure. You need to rewrite the eventhandling procedure too.************************************************************************************************ */static void hideTextRect( Rect *textRect ){textRect->top = 0;textRect->left = 0;textRect->bottom = 0;textRect->right = 0;InsetRect( textRect, kTextMargin, kTextMargin );}/* ************************************************************************************************hideTextRect:***************************************************************************************************Used in Graphic window, which hide the corresponding TextEdit Field. We hide the TextField insteadof creating another kind of window, because the event processing procedure is based on the WASTEDEMO. Thus, if we have two different kind of window structure. You need to rewrite the eventhandling procedure too.************************************************************************************************ */int isEditWindow(WindowPtr window){SInt16 i;for(i=1; i < Edit_Window; i++){if (Edit_Windows[i] == window)return i;}return 0;}void adjustEditPtr(SInt16 EditIndex){SInt16 i;for (i = EditIndex ; i < Edit_Window ; i++){Edit_Windows[i] = Edit_Windows[i+1];}Edit_Window --;}/*int R_ShowFiles(int nfile, char **fileName, char **title, char *WinTitle){*///int R_ShowFiles(int nfile, char **fileName, char **title, char *WinTitle, int x, char *xx)int R_ShowFiles(int nfile, char **fileName, char **title, char *WinTitle, Rboolean x, char *xx){Str255 PWTitle;Str255 name;FSSpec fsspec;OSErr readErr;SInt16 i;WEReference we;if (nfile <=0) return 1;readErr = DoNew();// Handle error for opening a new windowif (readErr != noErr)return 1;PWTitle[0] = strlen(WinTitle);strncpy( (char *)(&PWTitle[1]),WinTitle, PWTitle[0] );SetWTitle(Edit_Windows[Edit_Window-1], PWTitle);Help_Windows[Help_Window] = Edit_Windows[Edit_Window-1];Edit_Window --;Edit_Number --;Help_Window++;we = GetWindowWE ( Help_Windows[Help_Window-1]);for (i = 0; i < nfile; i++){if (title[i] && *title[i]){RnWWin(title[i], strlen(title[i]), we);RnWWin("\r\r", 2, we);}name[0] = strlen(fileName[i]);strncpy( (char *)(&name[1]),fileName[i], name[0] );FSMakeFSSpec(0,0,name,&fsspec);readErr = ReadTextFile ( &fsspec, we );if (readErr){RnWWin("NO FILE : ", 11, we);RnWWin(title[i], strlen(title[i]), we);RnWWin("\r", 1, we);readErr = noErr;}}// Handle Error about readingreturn 1;}int R_ShowFile(char *fileName, char *title){}void RnWWin(char* buf, SInt16 len, WEReference we ){SInt32 i;for ( i=0; i < len; i++){WEKey ( buf[i], NULL, we ) ;}}int isHelpWindow(WindowPtr window){SInt16 i;for(i=1; i<Help_Window; i++){if (window == Help_Windows[i]){return i;}}return 0;}