Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
HTMLControl.c
/* |
File: HTMLControl.c |
Description: |
HTMLControl implementation. |
Copyright: |
© Copyright 2000 Apple Computer, Inc. All rights reserved. |
Disclaimer: |
IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Change History (most recent first): |
Fri, Jan 28, 2000 -- created |
*/ |
#ifdef __APPLE_CC__ |
#include <Carbon/Carbon.h> |
#else |
#include <Carbon.h> |
#endif |
#include "HTMLControl.h" |
enum { |
kShiftKeyCode = 56 |
}; |
/* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus |
routine. In our focus switching routine this part code is understood |
as meaning 'the user has clicked in the control and we need to switch |
the current focus to ourselves before we can continue'. */ |
#define kUserClickedToFocusPart 100 |
/* kHTMLClickScrollDelayTicks is a time measurement in ticks used to |
slow the speed of 'auto scrolling' inside of our clickloop routine. |
This value prevents the text from wizzzzzing by while the mouse |
is being held down inside of the text area. */ |
#define kHTMLClickScrollDelayTicks 3 |
#define kNavButtonHeight 22 |
#define kNavButtonWidth 44 |
#define kNavButtonSpacing 5 |
/* STPTextPaneVars is a structure used for storing the the HTML Control's |
internal variables and state information. A handle to this record is |
stored in the pane control's reference value field using the |
SetControlReference routine. */ |
typedef struct { |
/* OS records referenced */ |
HRReference fHTMLRec; /* the txn record */ |
ControlHandle fUserPaneRec; /* handle to the user pane control */ |
WindowPtr fOwner; /* window containing control */ |
CGrafPtr fDrawingEnvironment; /* grafport where control is drawn */ |
/* flags */ |
Boolean fInFocus; /* true while the focus rect is drawn around the control */ |
Boolean fIsActive; /* true while the control is drawn in the active state */ |
Boolean fTEActive; /* reflects the activation state of the text edit record */ |
Boolean fInDialogWindow; /* true if displayed in a dialog window */ |
/* calculated locations */ |
Rect fRCachedBounds; /* area where the text is drawn */ |
Rect fRHTMLArea; /* area where the text is drawn */ |
Rect fRFocusOutline; /* rectangle used to draw the focus box */ |
Rect fRTextOutline; /* rectangle used to draw the border */ |
RgnHandle fTextBackgroundRgn; /* background region for the text, erased before calling TEUpdate */ |
} STPTextPaneVars; |
/* Univeral Procedure Pointer variables used by the |
HTML Control. These variables are set up |
the first time that HTMLOpenControl is called. */ |
ControlUserPaneDrawUPP gTPDrawProc = NULL; |
ControlUserPaneHitTestUPP gTPHitProc = NULL; |
ControlUserPaneTrackingUPP gTPTrackProc = NULL; |
ControlUserPaneIdleUPP gTPIdleProc = NULL; |
ControlUserPaneKeyDownUPP gTPKeyProc = NULL; |
ControlUserPaneActivateUPP gTPActivateProc = NULL; |
ControlUserPaneFocusUPP gTPFocusProc = NULL; |
static void CalculateHTMLControlRectangles(STPTextPaneVars **tpvars, Rect *bounds) { |
STPTextPaneVars *varsp; |
char state; |
/* set up our globals */ |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* basic outline and general areas */ |
varsp->fRHTMLArea = varsp->fRTextOutline = *bounds; |
varsp->fRFocusOutline = varsp->fRCachedBounds = *bounds; |
RectRgn(varsp->fTextBackgroundRgn, &varsp->fRHTMLArea); |
/* restore state */ |
HSetState((Handle) tpvars, state); |
} |
/* TPActivatePaneText activates or deactivates the text edit record |
according to the value of setActive. The primary purpose of this |
routine is to ensure each call is only made once. */ |
static void TPActivatePaneText(STPTextPaneVars **tpvars, Boolean setActive) { |
STPTextPaneVars *varsp; |
varsp = *tpvars; |
if (varsp->fTEActive != setActive) { |
varsp->fTEActive = setActive; |
if (setActive) |
HRActivate(varsp->fHTMLRec); |
else HRDeactivate(varsp->fHTMLRec); |
} |
} |
/* TPFocusPaneText set the focus state for the text record. */ |
static void TPFocusPaneText(STPTextPaneVars **tpvars, Boolean setFocus) { |
STPTextPaneVars *varsp; |
varsp = *tpvars; |
if (varsp->fInFocus != setFocus) { |
varsp->fInFocus = setFocus; |
/* no special processing for HTML structures */ |
} |
} |
/* TPPaneDrawProc is called to redraw the control and for update events |
referring to the control. This routine erases the text area's background, |
and redraws the text. This routine assumes the scroll bar has been |
redrawn by a call to DrawControls. */ |
static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) { |
STPTextPaneVars **tpvars, *varsp; |
char state; |
Rect bounds; |
/* set up our globals */ |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
RgnHandle clipSave; |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* save the drawing state */ |
SetPort((**tpvars).fDrawingEnvironment); |
/* verify our boundary */ |
GetControlBounds(theControl, &bounds); |
if ( ! EqualRect(&bounds, &varsp->fRCachedBounds) ) { |
CalculateHTMLControlRectangles(tpvars, &bounds); |
HRSetRenderingRect( varsp->fHTMLRec, &varsp->fRHTMLArea); |
} else { |
HRSetRenderingRect( varsp->fHTMLRec, &varsp->fRHTMLArea); |
} |
/* update the navigation controls */ |
SetPort((**tpvars).fDrawingEnvironment); |
GetClip((clipSave = NewRgn())); |
ClipRect(&varsp->fRHTMLArea); |
/* update the text region */ |
EraseRgn(varsp->fTextBackgroundRgn); |
HRDraw( varsp->fHTMLRec, varsp->fTextBackgroundRgn); |
/* restore the drawing environment */ |
SetClip(clipSave); |
DisposeRgn(clipSave); |
/* draw the text frame and focus frame (if necessary) */ |
DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); |
if ((**tpvars).fIsActive && varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, true); |
/* release our globals */ |
HSetState((Handle) tpvars, state); |
} |
} |
/* TPPaneHitTestProc is called when the control manager would |
like to determine what part of the control the mouse resides over. |
We also call this routine from our tracking proc to determine how |
to handle mouse clicks. */ |
static pascal ControlPartCode TPPaneHitTestProc(ControlHandle theControl, Point where) { |
STPTextPaneVars **tpvars; |
ControlPartCode result; |
char state; |
/* set up our locals and lock down our globals*/ |
result = 0; |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
/* find the region where we clicked */ |
if (PtInRect(where, &(**tpvars).fRHTMLArea)) { |
result = kHTMLTextPart; |
} else result = 0; |
/* release oure globals */ |
HSetState((Handle) tpvars, state); |
} |
return result; |
} |
/* TPPaneTrackingProc is called when the mouse is being held down |
over our control. This routine handles clicks in the text area |
and in the scroll bar. */ |
static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point startPt, ControlActionUPP actionProc) { |
STPTextPaneVars **tpvars, *varsp; |
char state; |
ControlPartCode partCodeResult; |
/* make sure we have some variables... */ |
partCodeResult = 0; |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
/* lock 'em down */ |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* we don't do any of these functions unless we're in focus */ |
if ( ! varsp->fInFocus) { |
WindowPtr owner; |
owner = GetControlOwner(theControl); |
ClearKeyboardFocus(owner); |
SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart); |
} |
/* find the location for the click */ |
switch (TPPaneHitTestProc(theControl, startPt)) { |
/* handle clicks in the text part */ |
case kHTMLTextPart: |
{ EventRecord ev; |
SetPort((**tpvars).fDrawingEnvironment); |
ev.what = mouseDown; |
ev.message = 0; |
ev.when = TickCount(); |
GetMouse(&ev.where); |
LocalToGlobal(&ev.where); |
ev.modifiers = 0; |
HRIsHREvent(&ev); |
} |
break; |
} |
HSetState((Handle) tpvars, state); |
} |
return partCodeResult; |
} |
/* TPPaneIdleProc is our user pane idle routine. When our text field |
is active and in focus, we use this routine to set the cursor. */ |
static pascal void TPPaneIdleProc(ControlHandle theControl) { |
STPTextPaneVars **tpvars, *varsp; |
/* set up locals */ |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
/* if we're not active, then we have nothing to say about the cursor */ |
if ((**tpvars).fIsActive) { |
char state; |
EventRecord ev; |
/* lock down the globals */ |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* set up our port */ |
SetPort(GetWindowPort(GetControlOwner(theControl))); |
/* fake a null event */ |
ev.what = nullEvent; |
ev.message = 0; |
ev.when = TickCount(); |
GetMouse(&ev.where); |
LocalToGlobal(&ev.where); |
ev.modifiers = 0; |
HRIsHREvent(&ev); |
/* clean up */ |
HSetState((Handle) tpvars, state); |
} |
} |
} |
/* TPPaneKeyDownProc is called whenever a keydown event is directed |
at our control. Here, we direct the keydown event to the text |
edit record and redraw the scroll bar and text field as appropriate. */ |
static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl, |
SInt16 keyCode, SInt16 charCode, SInt16 modifiers) { |
STPTextPaneVars **tpvars; |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
if ((**tpvars).fInFocus) { |
/* turn autoscrolling on and send the key event to text edit */ |
SetPort((**tpvars).fDrawingEnvironment); |
/* no operation here, but it would be cool tu use the arrow |
keys and the page up and page down keys for scrolling... */ |
} |
} |
return kControlEntireControl; |
} |
/* TPPaneActivateProc is called when the window containing |
the user pane control receives activate events. Here, we redraw |
the control and it's text as necessary for the activation state. */ |
static pascal void TPPaneActivateProc(ControlHandle theControl, Boolean activating) { |
Rect bounds; |
STPTextPaneVars **tpvars, *varsp; |
char state; |
/* set up locals */ |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* de/activate the text edit record */ |
SetPort((**tpvars).fDrawingEnvironment); |
GetControlBounds(theControl, &bounds); |
varsp->fIsActive = activating; |
TPActivatePaneText(tpvars, varsp->fIsActive /* && varsp->fInFocus */ ); |
/* redraw the frame */ |
DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); |
if (varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive); |
HSetState((Handle) tpvars, state); |
} |
} |
/* TPPaneFocusProc is called when every the focus changes to or |
from our control. Herein, switch the focus appropriately |
according to the parameters and redraw the control as |
necessary. */ |
static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlFocusPart action) { |
ControlPartCode focusResult; |
STPTextPaneVars **tpvars, *varsp; |
char state; |
/* set up locals */ |
focusResult = kControlFocusNoPart; |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
if (tpvars != NULL) { |
state = HGetState((Handle) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is |
tabbing forwards (or shift tabbing backwards) through the items in the dialog, |
and kControlFocusNextPart will be received. When the user clicks in our field |
and it is not the current focus, then the constant kUserClickedToFocusPart will |
be received. The constant kControlFocusNoPart will be received when our control |
is the current focus and the user clicks in another control. In your focus routine, |
you should respond to these codes as follows: |
kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw |
the control and the focus rectangle as necessary. |
kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off |
depending on its current state. redraw the control and the focus rectangle |
as appropriate for the new focus state. If the focus state is 'off', return the constant |
kControlFocusNoPart, otherwise return a non-zero part code. |
kUserClickedToFocusPart - is a constant defined for this example. You should |
define your own value for handling click-to-focus type events. */ |
/* save the drawing state */ |
SetPort((**tpvars).fDrawingEnvironment); |
/* calculate the next highlight state */ |
switch (action) { |
default: |
case kControlFocusNoPart: |
TPFocusPaneText(tpvars, false); |
focusResult = kControlFocusNoPart; |
break; |
case kUserClickedToFocusPart: |
TPFocusPaneText(tpvars, true); |
focusResult = 1; |
break; |
case kControlFocusPrevPart: |
case kControlFocusNextPart: |
TPFocusPaneText(tpvars, ( ! varsp->fInFocus)); |
focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart; |
break; |
} |
TPActivatePaneText(tpvars, varsp->fIsActive /* && varsp->fInFocus */ ); |
/* redraw the text fram and focus rectangle to indicate the |
new focus state */ |
DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); |
DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive && varsp->fInFocus); |
/* done */ |
HSetState((Handle) tpvars, state); |
} |
return focusResult; |
} |
/* HTMLOpenControl initializes a user pane control so it will be drawn |
and will behave as a scrolling text edit field inside of a window. |
This routine performs all of the initialization steps necessary, |
except it does not create the user pane control itself. theControl |
should refer to a user pane control that you have either created |
yourself or extracted from a dialog's control heirarchy using |
the GetDialogItemAsControl routine. */ |
OSStatus HTMLOpenControl(ControlHandle theControl) { |
Rect bounds; |
WindowPtr theWindow; |
STPTextPaneVars **tpvars, *varsp; |
OSStatus err; |
if ( ! HRHTMLRenderingLibAvailable()) return paramErr; |
/* set up our globals */ |
if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc); |
if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc); |
if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc); |
if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc); |
if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc); |
if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc); |
if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc); |
/* allocate our private storage */ |
tpvars = (STPTextPaneVars **) NewHandleClear(sizeof(STPTextPaneVars)); |
SetControlReference(theControl, (long) tpvars); |
HLock((Handle) tpvars); |
varsp = *tpvars; |
/* set the initial settings for our private data */ |
varsp->fInFocus = false; |
varsp->fIsActive = true; |
varsp->fTEActive = false; |
varsp->fUserPaneRec = theControl; |
theWindow = varsp->fOwner = GetControlOwner(theControl); |
varsp->fDrawingEnvironment = GetWindowPort(varsp->fOwner); |
SetPort(varsp->fDrawingEnvironment); |
varsp->fInDialogWindow = ( GetWindowKind(varsp->fOwner) == kDialogWindowKind ); |
varsp->fTextBackgroundRgn = NewRgn(); |
/* set up the user pane procedures */ |
SetControlData(theControl, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc); |
SetControlData(theControl, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc); |
SetControlData(theControl, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc); |
SetControlData(theControl, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc); |
SetControlData(theControl, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc); |
SetControlData(theControl, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc); |
SetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc); |
/* calculate the rectangles used by the control */ |
GetControlBounds(theControl, &bounds); |
CalculateHTMLControlRectangles(tpvars, &bounds); |
/* create the new edit field */ |
err = HRNewReference( &varsp->fHTMLRec, kHRRendererHTML32Type, varsp->fDrawingEnvironment); |
if (err == NULL) goto bail; |
HRSetRenderingRect( varsp->fHTMLRec, &varsp->fRHTMLArea); |
/* unlock our storage */ |
HUnlock((Handle) tpvars); |
/* perform final activations and setup for our text field. Here, |
we assume that the window is going to be the 'active' window. */ |
TPActivatePaneText(tpvars, varsp->fIsActive /* && varsp->fInFocus */ ); |
/* all done */ |
return noErr; |
bail: |
return err; |
} |
/* HTMLCloseControl deallocates all of the structures allocated |
by HTMLOpenControl. */ |
OSStatus HTMLCloseControl(ControlHandle theControl) { |
STPTextPaneVars **tpvars; |
/* set up locals */ |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
/* release our sub records */ |
HRDisposeReference((**tpvars).fHTMLRec); |
/* delete our private storage */ |
DisposeHandle((Handle) tpvars); |
/* zero the control reference */ |
SetControlReference(theControl, 0); |
return noErr; |
} |
/* STUPCreateControl creates a new user pane control and then it passes it |
to STUPOpenControl to initialize it as a scrolling text user pane control. */ |
OSStatus HTMLCreateControl(WindowPtr theWindow, Rect *bounds, ControlHandle *theControl) { |
short featurSet; |
/* the following feature set can be specified in CNTL resources by using |
the value 1214. When creating a user pane control, we pass this value |
in the 'value' parameter. */ |
featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle |
| kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground |
| kControlGetsFocusOnClick | kControlSupportsLiveFeedback; |
/* create the control */ |
*theControl = NewControl(theWindow, bounds, "\p", true, featurSet, 0, featurSet, kControlUserPaneProc, 0); |
/* set up the STUP specific features and data */ |
HTMLOpenControl(*theControl); |
/* all done.... */ |
return noErr; |
} |
/* STUPDisposeControl calls STUPCloseControl and then it calls DisposeControl. */ |
OSStatus HTMLDisposeControl(ControlHandle theControl) { |
/* deallocate the STUP specific data */ |
HTMLCloseControl(theControl); |
/* deallocate the user pane control itself */ |
DisposeControl(theControl); |
return noErr; |
} |
/* HTMLGotoURL displays HTML file referred to by the url in the |
rendering control. if addToHistory is true, then the window |
will be added to the window's history list. */ |
OSStatus HTMLDisplayFile(ControlHandle theControl, FSSpec *theFile) { |
STPTextPaneVars **tpvars; |
/* set up locals */ |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
/* display the file */ |
return HRGoToFile( (**tpvars).fHTMLRec, theFile, true, true); |
} |
/* HTMLDisplayBuffer displays the HTML described by the buffer. */ |
OSStatus HTMLDisplayBuffer(ControlHandle theControl, char *buffer, long bytecount) { |
STPTextPaneVars **tpvars; |
/* set up locals */ |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
/* display the file */ |
return HRGoToPtr( (**tpvars).fHTMLRec, buffer, bytecount, false, true); |
} |
/* HTMLDisplayHandle displays the HTML in the handle htmlData. */ |
OSStatus HTMLDisplayHandle(ControlHandle theControl, Handle htmlData) { |
STPTextPaneVars **tpvars; |
char state; |
OSStatus err; |
/* set up locals, verify parameters */ |
if (htmlData == NULL || theControl == NULL) return paramErr; |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
/* display the file */ |
state = HGetState(htmlData); |
HLock(htmlData); |
err = HRGoToPtr( (**tpvars).fHTMLRec, (char*) (*htmlData), GetHandleSize(htmlData), false, true); |
HSetState(htmlData, state); |
return err; |
} |
/* IsHTMLControl returns true if theControl is not NULL |
and theControl refers to a HTML Control. */ |
Boolean IsHTMLControl(ControlHandle theControl) { |
Size theSize; |
ControlUserPaneFocusUPP localFocusProc; |
/* a NULL control is not a mUP control */ |
if (theControl == NULL) return false; |
/* check if the control is using our focus procedure */ |
theSize = sizeof(localFocusProc); |
if (GetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, |
sizeof(localFocusProc), &localFocusProc, &theSize) != noErr) return false; |
if (localFocusProc != gTPFocusProc) return false; |
/* all tests passed, it's a mUP control */ |
return true; |
} |
/* HTMLDisplayHandle displays the HTML in the handle htmlData. */ |
OSStatus HTMLDisplayURL(ControlHandle theControl, char const* url) { |
STPTextPaneVars **tpvars; |
OSStatus err; |
/* set up locals, verify parameters */ |
if (url == NULL || theControl == NULL) return paramErr; |
tpvars = (STPTextPaneVars **) GetControlReference(theControl); |
/* display the file */ |
err = HRGoToURL( (**tpvars).fHTMLRec, url, true, true); |
return err; |
} |
#if 0 |
/* RWGotoURL displays HTML file referred to by the url in the |
rendering window. if addToHistory is true, then the window |
will be added to the window's history list. */ |
OSStatus RWGotoURL(WindowPtr rWin, char* url, Boolean addToHistory) { |
RWindowHandle rwv; |
OSStatus err; |
Point origin = {0, 0}; |
Rect donedrawingbox; |
/* set up locals */ |
rwv = (RWindowHandle) GetWRefCon(rWin); |
/* if the URL does not contain an anchor, then scroll |
the HTML view to the origin. */ |
if ( ! URLContainsAnchor(url)) { |
err = HRScrollToLocation((**rwv).renderer, &origin); |
if (err != noErr) goto bail; |
} |
/* ask the rendering object to display the HTML page |
referred to by the URL. note, we pass the addToHistory to |
this routine which in turn passes it to our MyNewURLProc |
routine. */ |
err = HRGoToURL((**rwv).renderer, url, addToHistory, false); |
if (err != noErr) goto bail; |
/* draw the new page */ |
err = HRDraw((**rwv).renderer, NULL); |
if (err != noErr) goto bail; |
/* if addToHistory is false, then we would not |
have re-drawn the buttons inside of our MyNewURLProc |
routine so we should draw them here. */ |
if ( ! addToHistory) |
RedrawWindowButtons(rwv); |
/* we validate the areas that were drawn by this |
routine. This is to avoid unnecessary redraws when |
the window is first opened. When the window is opened, |
an update event will be posted for its entire contents. |
These calls prevent the areas we have just drawn from |
being re-drawn when the update event is processed. */ |
SetRect(&donedrawingbox, 0, 0, 32*3, 32); |
ValidWindowRect(rWin, &donedrawingbox); |
GetPortBounds(GetWindowPort((**rwv).rwindow), &donedrawingbox); |
donedrawingbox.top += 33; |
ValidWindowRect(rWin, &donedrawingbox); |
/* done */ |
return noErr; |
bail: |
return err; |
} |
/* GetApplicationFolder returns the volume reference number and |
directory id of the folder containing the application. */ |
OSStatus GetApplicationFolder(FSSpec *spec) { |
OSStatus err; |
FCBPBRec fcpb; |
Str255 name; |
CInfoPBRec cat; |
Handle h; |
h = GetResource('vTeZ', 0); |
if (h == NULL) return resNotFound; |
BlockZero(&fcpb, 0); |
fcpb.ioVRefNum = 0; |
fcpb.ioNamePtr = name; |
fcpb.ioFCBParID = 0; |
fcpb.ioRefNum = HomeResFile(h); |
fcpb.ioFCBIndx = 0; |
if ((err = PBGetFCBInfoSync(&fcpb)) != noErr) return err; |
BlockZero(&cat, 0); |
cat.dirInfo.ioNamePtr = name; |
cat.dirInfo.ioVRefNum = fcpb.ioFCBVRefNum; |
cat.dirInfo.ioFDirIndex = -1; |
cat.dirInfo.ioDrDirID = fcpb.ioFCBParID; |
err = PBGetCatInfoSync(&cat); |
if (err != noErr) return err; |
err = FSMakeFSSpec(fcpb.ioFCBVRefNum, cat.dirInfo.ioDrParID, name, spec); |
if (err != noErr) return err; |
return noErr; |
} |
/* GetApplicationFolder returns a URL referring to the folder |
containing the application. If successful, *url is set |
to a new handle containing the URL. It is the caller's |
responsibility to dispose of this handle. */ |
OSStatus GetApplicationFolderURL(Handle *url) { |
OSStatus err; |
FSSpec spec; |
Handle theURL; |
/* set up locals to a known state */ |
theURL = NULL; |
/* find the application's folder */ |
err = GetApplicationFolder(&spec); |
if (err != noErr) goto bail; |
/* create a new handle for storing the URL */ |
theURL = NewHandle(0); |
if (theURL == NULL) { err = memFullErr; goto bail; } |
/* ask the HTML rendering library to convert |
the FSSpec into a URL */ |
err = HRUtilGetURLFromFSSpec(&spec, theURL); |
if (err != noErr) goto bail; |
/* add a slash at the end of the name, if one is not there */ |
if ( (*theURL)[GetHandleSize(theURL) - 2] != '/') |
Munger(theURL, (GetHandleSize(theURL) - 1), NULL, 0, "/", 1); |
/* return the URL */ |
*url = theURL; |
return noErr; |
bail: |
if (theURL != NULL) DisposeHandle(theURL); |
return err; |
} |
/* RWGotoAppRelLink displays HTML file referred to by the application |
relative link in the rendering window. if addToHistory is true, then |
the window will be added to the window's history list. */ |
OSStatus RWGotoAppRelLink(WindowPtr rWin, char* linkstr, Boolean addToHistory) { |
OSStatus err; |
Handle rootURL, fullURL; |
/* set up our locals */ |
rootURL = fullURL = NULL; |
/* get the URL for the application's folder */ |
err = GetApplicationFolderURL(&rootURL); |
if (err != noErr) goto bail; |
/* allocate a handle for storing the full URL */ |
fullURL = NewHandle(0); |
if (fullURL == NULL) { err = memFullErr; goto bail; } |
/* ask the HTML rendering library to combine |
the url and the link to make a complete URL */ |
HLock(rootURL); |
err = HRUtilCreateFullURL(*rootURL, linkstr, fullURL); |
if (err != noErr) goto bail; |
HUnlock(rootURL); |
/* call the RWGotoURL to bring the HTML file into view. */ |
MoveHHi(fullURL); |
HLock(fullURL); |
err = RWGotoURL(rWin, *fullURL, addToHistory); |
if (err != noErr) goto bail; |
/* clean up our locals */ |
DisposeHandle(rootURL); |
DisposeHandle(fullURL); |
/* done */ |
return noErr; |
bail: |
/* on error, clean up and return the error. */ |
if (rootURL != NULL) DisposeHandle(rootURL); |
if (fullURL != NULL) DisposeHandle(fullURL); |
return err; |
} |
#endif |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-30