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.
ExtraStuff.c
/* |
File: ExtraStuff.c |
Description: This sample code demonstrates the basic usage of the NSL API for finding network |
services using SLP, NBP, and Directory Services. |
Author: MK |
Copyright: © Copyright 2001 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): |
5/21/01 1.0d1 |
*/ |
#include "NSLMiniBrowser.h" |
#include <ctype.h> |
WindowRef gAboutWindow; |
WindowRef gRegisterWindow; |
SInt16 gPreviousItem = 1; |
extern IBNibRef gNibRef; |
extern EventLoopTimerUPP gMyStartLookupTimerUPP; |
extern EventLoopTimerUPP gMyNeighborhoodTimerUPP; |
extern EventLoopTimerUPP gMyServicesTimerUPP; |
extern EventLoopTimerUPP gMyYieldToAnyThreadTimerUPP; |
extern EventLoopTimerUPP gMyRefreshBrowserTimerUPP; |
extern MPQueueID gQueue; |
extern Boolean gEventHandled; |
extern WindowRef gMainWindow; |
extern CFStringRef gData[kMaxNeighborhoods * kMaxServicesPerNeighborhood + kMaxNeighborhoods]; |
extern NeighborhoodInfo gNeighborhoodInfo; |
extern LookupInfo gLookupInfo[kMaxNeighborhoods + 1]; |
extern ControlRef gDataBrowserControl; |
extern TimerInfo gYieldTimerInfo; |
extern Boolean gSystemIsMacOSX; |
OSStatus LoadRegisterWindowFromNibFile(); |
OSStatus LoadAboutWindowFromNibFile(); |
OSStatus LoadMainWindowFromNibFile(); |
OSStatus MyStartLookupTimer(EventLoopTimerRef inTimer, void * inUserData); |
extern OSStatus InitDataBrowserControl(); |
extern void DoNeighborhoodLookup(DataBrowserItemID parentID); |
extern void CancelNeighborhoodLookup(DataBrowserItemID itemID); |
extern void DoServicesLookup(DataBrowserItemID parentID); |
extern void CancelServicesLookup(DataBrowserItemID itemID); |
extern void DoRegisterURL(); |
extern void DoDeregisterURL(); |
void |
ParseURL(CFStringRef urlPtr, CFStringRef * name) |
{ |
CFIndex count; |
char * tempPtr; |
if (urlPtr) |
{ |
tempPtr = (char *)strstr(CFStringGetCStringPtr(urlPtr, CFStringGetSystemEncoding()), kAppleTalkKey); |
if (tempPtr != NULL) |
{ |
tempPtr += 5; |
count = 0; |
while (tempPtr[count] != '\0' && tempPtr[count] != ':') count++; |
*name = CFStringCreateWithBytes(NULL, tempPtr, count, CFStringGetSystemEncoding(), false); |
} |
else if (CFStringFindWithOptions(urlPtr, CFSTR("?"), CFRangeMake(0, CFStringGetLength(urlPtr)), 0, NULL) == false) |
{ |
*name = CFStringCreateCopy(NULL, urlPtr); |
} |
else |
{ |
tempPtr = (char *)strstr(CFStringGetCStringPtr(urlPtr, CFStringGetSystemEncoding()), kNameKey); |
if (tempPtr != NULL) |
{ |
tempPtr += 5; |
count = 0; |
while (tempPtr[count] != '\0' && tempPtr[count] != '&') count++; |
*name = CFStringCreateWithBytes(NULL, tempPtr, count, CFStringGetSystemEncoding(), false); |
} |
else |
{ |
*name = CFStringCreateCopy(NULL, urlPtr); |
} |
} |
} |
else |
{ |
*name = NULL; |
} |
} |
void |
CreateAddItemEvent() |
{ |
EventRef event; |
OSStatus err; |
err = MacCreateEvent(NULL, kEventClassApplication, kAddItemToBrowser, GetCurrentEventTime(), kEventAttributeNone, &event); |
if (err == noErr) |
{ |
err = PostEventToQueue(GetMainEventQueue(), event, kEventPriorityHigh); |
if (err != noErr) |
{ |
gEventHandled = true; |
} |
ReleaseEvent(event); |
} |
else |
{ |
gEventHandled = true; |
} |
} |
void |
AddNeighborhoodToList(char * neighborhood, UInt32 parentID) |
{ |
CFStringRef tempNeighborhood = NULL; |
CFComparisonResult result = -1; |
UInt32 neighborhoodID, i; |
if (neighborhood) |
{ |
tempNeighborhood = CFStringCreateWithCString(NULL, neighborhood, CFStringGetSystemEncoding()); |
if (tempNeighborhood) |
{ |
// Check if the item is already in our list. If it is, "result" will be kCFCompareEqualTo. |
for (i = 0; i < kMaxNeighborhoods; i++) |
{ |
if (gData[i] && gNeighborhoodInfo.parentID[i] == parentID) |
{ |
result = CFStringCompare(tempNeighborhood, gData[i], kCFCompareCaseInsensitive); |
if (result == kCFCompareEqualTo) break; |
} |
} |
if (result != kCFCompareEqualTo) |
{ |
// Only add the item if the parent neighborhood is open and visible in the Data Browser. |
if ((gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1]) || parentID == 0) |
{ |
neighborhoodID = IncrementAtomic(&gNeighborhoodInfo.neighborhoodCount); |
if (++neighborhoodID < kMaxNeighborhoods) |
{ |
gNeighborhoodInfo.parentID[neighborhoodID - 1] = parentID; |
gData[neighborhoodID - 1] = CFStringCreateCopy(NULL, tempNeighborhood); |
AddDataBrowserItems(gDataBrowserControl, parentID, 1, &neighborhoodID, kNameColumn); |
if (parentID == kDataBrowserNoItem) |
{ |
gNeighborhoodInfo.isDefaultNeighborhood[neighborhoodID - 1] = true; |
} |
else |
{ |
gNeighborhoodInfo.isDefaultNeighborhood[neighborhoodID - 1] = false; |
} |
} |
else |
{ |
DecrementAtomic(&gNeighborhoodInfo.neighborhoodCount); |
} |
} |
} |
else if (result == kCFCompareEqualTo) |
{ |
if (gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1]) |
{ |
neighborhoodID = i + 1; |
if (gNeighborhoodInfo.isNeighborhoodVisible[i] == false) |
{ |
AddDataBrowserItems(gDataBrowserControl, parentID, 1, &neighborhoodID, kNameColumn); |
if (gNeighborhoodInfo.isNeighborhoodOpen[i]) |
{ |
OpenDataBrowserContainer(gDataBrowserControl, neighborhoodID); |
} |
} |
else |
{ |
if (gNeighborhoodInfo.isNeighborhoodOpen[i]) |
{ |
CancelServicesLookup(parentID); |
CancelNeighborhoodLookup(parentID); |
InstallEventLoopTimer(GetMainEventLoop(), 0.3, 0, gMyStartLookupTimerUPP, (void *)(neighborhoodID), NULL); |
} |
} |
} |
} |
CFRelease(tempNeighborhood); |
} |
free(neighborhood); |
} |
} |
void |
AddServiceToPopupMenu(char * serviceType, UInt16 serviceLen, UInt16 * serviceMenuItem) |
{ |
ControlID controlID = { kNSLSample, kServicesTypePopup }; |
ControlRef control; |
CFStringRef tempService = NULL; |
CFStringRef menuText = NULL; |
char tempServiceString[kMaxTypeNameLength]; |
CFComparisonResult result = -1; |
MenuRef menu; |
OSStatus err = noErr; |
short itemCount, i; |
if (serviceType) |
{ |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
strncpy(tempServiceString, serviceType, serviceLen); |
tempServiceString[serviceLen] = '\0'; |
for (i = 0; i < serviceLen; i++) tempServiceString[i] = toupper(tempServiceString[i]); |
tempService = CFStringCreateWithCString(NULL, tempServiceString, CFStringGetSystemEncoding()); |
if (tempService) |
{ |
menu = GetControlPopupMenuHandle(control); |
itemCount = CountMenuItems(menu); |
for (i = 1; i <= itemCount; i ++) |
{ |
CopyMenuItemTextAsCFString(menu, i , &menuText); |
if (menuText) |
{ |
result = CFStringCompare(menuText, tempService, kCFCompareCaseInsensitive); |
if (result == kCFCompareEqualTo) |
{ |
if (serviceMenuItem) *serviceMenuItem = i; |
break; |
} |
} |
} |
if (result != kCFCompareEqualTo) |
{ |
err = AppendMenuItemTextWithCFString(menu, tempService, 0, 0, serviceMenuItem); |
if (err == noErr) |
{ |
SetControlMaximum(control, itemCount + 1); |
if (serviceMenuItem) *serviceMenuItem = itemCount + 1; |
} |
CFRelease(tempService); |
} |
} |
} |
} |
} |
void |
UpdateItemCount() |
{ |
ControlID controlID = { kNSLSample, kServicesCountText }; |
ControlRef control; |
Str255 countStr; |
char count[16]; |
UInt32 itemCount; |
static UInt32 previousItemCount = 0; |
OSStatus err = noErr; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
err = GetDataBrowserItemCount(gDataBrowserControl, 0, true, kDataBrowserItemAnyState, &itemCount); |
// Only update if the count has actually changed since last time. |
if (err == noErr && previousItemCount != itemCount) |
{ |
previousItemCount = itemCount; |
NumToString (itemCount, countStr); |
CopyPascalStringToC(countStr, count); |
if (itemCount == 1) |
{ |
strcat(count, " Item"); |
SetControlData(control, kControlNoPart, kControlEditTextTextTag, strlen(count), count); |
ShowControl(control); |
} |
else |
{ |
strcat(count, " Items"); |
SetControlData(control, kControlNoPart, kControlEditTextTextTag, strlen(count), count); |
ShowControl(control); |
} |
DrawOneControl(control); |
DrawOneControl(gDataBrowserControl); |
} |
} |
} |
void |
GetServiceTypeToLookup(CFMutableStringRef * serviceString, UInt16 * serviceMenuItem) |
{ |
ControlID controlID = { kNSLSample, kServicesTypePopup }; |
ControlRef control; |
CFStringRef outString; |
MenuRef menu; |
SInt16 value; |
OSStatus err; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
value = GetControlValue(control); |
if (serviceString) |
{ |
menu = GetControlPopupMenuHandle(control); |
if (menu) |
{ |
CopyMenuItemTextAsCFString(menu, value, &outString); |
if (serviceString) |
{ |
*serviceString = CFStringCreateMutableCopy(NULL, CFStringGetLength(outString), outString); |
CFStringLowercase(*serviceString, NULL); |
} |
if (outString) CFRelease(outString); |
} |
} |
if (serviceMenuItem) *serviceMenuItem = value; |
} |
} |
void |
SetServiceTypePopupMenu(UInt16 serviceMenuItem) |
{ |
ControlID controlID = { kNSLSample, kServicesTypePopup }; |
ControlRef control; |
OSStatus err; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
SetControlValue(control, serviceMenuItem); |
gPreviousItem = serviceMenuItem; |
} |
} |
void |
AddServiceToList(char * url, DataBrowserItemID parentID) |
{ |
CFMutableStringRef serviceType; |
char tempServiceString[kMaxTypeNameLength]; |
char * svcString = NULL; |
UInt16 svcLen; |
DataBrowserItemID itemID; |
CFComparisonResult result = -1; |
int i; |
CFStringRef tempURL; |
OSStatus err; |
if (url) |
{ |
err = NSLGetServiceFromURL(url, &svcString, &svcLen); |
if (err == noErr) |
{ |
strncpy(tempServiceString, svcString, svcLen); |
tempServiceString[svcLen] = '\0'; |
// Convert to lowercase so we can do a compare. |
for (i = 0; i < svcLen; i++) tempServiceString[i] = tolower(tempServiceString[i]); |
// Gets the current value of the service type from the popup menu. |
GetServiceTypeToLookup(&serviceType, NULL); |
// Make sure we're only adding items for the service type that's selected in the popup menu. |
if (strcmp(CFStringGetCStringPtr(serviceType, CFStringGetSystemEncoding()), tempServiceString) == 0) |
{ |
// Check if we're under the limit for maximum services per neighborhood. |
if (gNeighborhoodInfo.neighborhoodSize[parentID - 1] < kMaxServicesPerNeighborhood) |
{ |
// Check if the item is already in our list. If it is, "result" will be 0. |
for (i = 0; i < gNeighborhoodInfo.neighborhoodSize[parentID - 1]; i++) |
{ |
tempURL = CFStringCreateWithCString(NULL, url, CFStringGetSystemEncoding()); |
if (tempURL) |
{ |
result = CFStringCompare(tempURL, gData[kMaxServicesPerNeighborhood*(parentID-1)+kMaxNeighborhoods+i], kCFCompareCaseInsensitive); |
CFRelease(tempURL); |
if (result == kCFCompareEqualTo) break; |
} |
} |
// As long as the item isn't in the list and the DataBrowser container is open, add the item. |
if (result != kCFCompareEqualTo && gNeighborhoodInfo.isNeighborhoodOpen[parentID - 1] && gNeighborhoodInfo.isNeighborhoodVisible[parentID - 1]) |
{ |
// Increment the count of the services in this neighborhood. |
gNeighborhoodInfo.neighborhoodSize[parentID - 1]++; |
itemID = kMaxServicesPerNeighborhood * (parentID - 1) + kMaxNeighborhoods + gNeighborhoodInfo.neighborhoodSize[parentID - 1]; |
gData[itemID - 1] = CFStringCreateWithCString(NULL, url, CFStringGetSystemEncoding()); |
AddDataBrowserItems(gDataBrowserControl, parentID, 1, &itemID, kNameColumn); |
} |
} |
} |
} |
free(url); |
} |
} |
void |
CancelLookups(UInt32 parentID) |
{ |
int i; |
for (i = 0; i < kMaxNeighborhoods; i++) |
{ |
if (gNeighborhoodInfo.parentID[i] == parentID) |
{ |
CancelLookups(i + 1); |
} |
} |
CancelServicesLookup(parentID); |
CancelNeighborhoodLookup(parentID); |
} |
void |
RemoveServicesFromNeighborhood(DataBrowserItemID parentID, Boolean removeFromDataBrowser) |
{ |
UInt32 i, itemID; |
// Only remove items if the neighborhood actually has items in it. |
if (gNeighborhoodInfo.neighborhoodSize[parentID - 1] > 0) |
{ |
if (removeFromDataBrowser) |
{ |
// Remove all items from the specified neighborhood. |
RemoveDataBrowserItems(gDataBrowserControl, parentID, 0, NULL, kDataBrowserItemNoProperty); |
} |
// Free all the memory allocated to store the URLs. |
for (i = 0; i < gNeighborhoodInfo.neighborhoodSize[parentID - 1]; i++) |
{ |
itemID = kMaxServicesPerNeighborhood * (parentID - 1) + kMaxNeighborhoods + i; |
if (gData[itemID]) CFRelease(gData[itemID]); |
} |
// Reset the count for this neighborhood to 0. |
gNeighborhoodInfo.neighborhoodSize[parentID - 1] = 0; |
} |
} |
void |
RemoveItemsFromList(DataBrowserItemID parentID) |
{ |
UInt32 i; |
for (i = 0; i < kMaxNeighborhoods; i++) |
{ |
if (gNeighborhoodInfo.parentID[i] == parentID) |
{ |
RemoveItemsFromList(i + 1); |
} |
} |
RemoveServicesFromNeighborhood(parentID, true); |
} |
OSStatus |
GetURLToRegister(char * url, char * neighborhood) |
{ |
ControlID controlID1 = { kNSLSample, kAddressEditText }; |
ControlID controlID2 = { kNSLSample, kNeighborhoodEditText }; |
ControlRef control; |
Size actualSize; |
OSStatus err; |
err = GetControlByID(gRegisterWindow, &controlID1, &control); |
if (err == noErr) |
{ |
// Get the address the user typed into the Register sheet. |
err = GetControlData(control, 0, kControlEditTextTextTag, kMaxStringLength, url, &actualSize); |
if (err == noErr) |
{ |
url[actualSize] = '\0'; |
// Get the neighborhood the user typed into the Register sheet. |
err = GetControlByID(gRegisterWindow, &controlID2, &control); |
if (err == noErr) |
{ |
err = GetControlData(control, 0, kControlEditTextTextTag, kMaxStringLength, neighborhood, &actualSize); |
if (err == noErr) neighborhood[actualSize] = '\0'; |
} |
} |
} |
return err; |
} |
void |
DoMyErrorAlert() |
{ |
AlertStdAlertParamRec param = { true, false, NULL, "\pOK", NULL, NULL, 1, 0, kWindowAlertPositionParentWindow }; |
ConstStr255Param errorString = "\pYou need to select an item first."; |
ConstStr255Param solutionString = "\pSelect an item from the list that you previously registered and then click Deregister."; |
SInt16 outItemHit; |
StandardAlert(kAlertNoteAlert, errorString, solutionString, ¶m, &outItemHit); |
} |
OSStatus |
MyNeighborhoodTimer(EventLoopTimerRef inTimer, void * inUserData) |
{ |
DataBrowserItemID parentID = (DataBrowserItemID)inUserData; |
CancelNeighborhoodLookup(parentID); |
return noErr; |
} |
OSStatus |
MyServicesTimer(EventLoopTimerRef inTimer, void * inUserData) |
{ |
DataBrowserItemID parentID = (DataBrowserItemID)inUserData; |
CancelServicesLookup(parentID); |
return noErr; |
} |
OSStatus |
MyStartLookupTimer(EventLoopTimerRef inTimer, void * inUserData) |
{ |
DataBrowserItemID parentID = (DataBrowserItemID)inUserData; |
if (gLookupInfo[parentID].sLookupActive == false) |
{ |
DoServicesLookup(parentID); |
} |
if (gLookupInfo[parentID].nLookupActive == false) |
{ |
DoNeighborhoodLookup(parentID); |
} |
return noErr; |
} |
OSStatus |
MyYieldToAnyThreadTimer(EventLoopTimerRef inTimer, void * inUserData) |
{ |
YieldToAnyThread(); |
return noErr; |
} |
OSStatus |
MyControlInterceptor(EventHandlerCallRef inCallRef, EventRef inEvent, void * inUserData) |
{ |
long index = (long)inUserData; |
switch (index) |
{ |
case kRegisterAddressButton: |
HideSheetWindow(gRegisterWindow); |
DoRegisterURL(); |
DisposeWindow(gRegisterWindow); |
gRegisterWindow = NULL; |
break; |
case kCancelRegisterButton: |
HideSheetWindow(gRegisterWindow); |
DisposeWindow(gRegisterWindow); |
gRegisterWindow = NULL; |
break; |
} |
return noErr; |
} |
static void |
DoActivateControls() |
{ |
ControlID controlID = { kNSLSample, 0 }; |
ControlRef control; |
OSStatus err = noErr; |
if (gDataBrowserControl) ActivateControl(gDataBrowserControl); |
controlID.id = kServicesCountText; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) ActivateControl(control); |
controlID.id = kServicesTypeText; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) ActivateControl(control); |
controlID.id = kServicesTypePopup; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) ActivateControl(control); |
controlID.id = kDeregisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) ActivateControl(control); |
controlID.id = kDeregisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) ActivateControl(control); |
controlID.id = kRegisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) ActivateControl(control); |
} |
static void |
DoDeactivateControls() |
{ |
ControlID controlID = { kNSLSample, 0 }; |
ControlRef control; |
OSStatus err = noErr; |
if (gDataBrowserControl) DeactivateControl(gDataBrowserControl); |
controlID.id = kServicesCountText; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) DeactivateControl(control); |
controlID.id = kServicesTypeText; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) DeactivateControl(control); |
controlID.id = kServicesTypePopup; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) DeactivateControl(control); |
controlID.id = kDeregisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) DeactivateControl(control); |
controlID.id = kDeregisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) DeactivateControl(control); |
controlID.id = kRegisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) DeactivateControl(control); |
} |
static void |
DoMoveControls(SInt16 heighDiff, SInt16 widthDiff) |
{ |
ControlID controlID = { kNSLSample, 0 }; |
ControlRef control; |
Rect browserBounds; |
Rect outRect; |
static Point button1 = { 0, 0 }; |
static Point button2 = { 0, 0 }; |
static Point popup = { 0, 0 }; |
static Point popuptext = { 0, 0 }; |
OSStatus err = noErr; |
if (gDataBrowserControl) |
{ |
GetControlBounds(gDataBrowserControl, &browserBounds); |
browserBounds.bottom += heighDiff; |
browserBounds.right += widthDiff; |
SetControlBounds(gDataBrowserControl, &browserBounds); |
if (heighDiff < 0 || widthDiff < 0) |
{ |
err = SetThemeWindowBackground(gMainWindow, kThemeBrushMovableModalBackground, true); |
} |
} |
controlID.id = kRegisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
if (button2.h == 0) |
{ |
GetControlBounds(control, &outRect); |
button2.v = outRect.top; |
button2.h = outRect.left; |
} |
button2.v += heighDiff; |
button2.h += widthDiff; |
MoveControl(control, button2.h, button2.v); |
} |
controlID.id = kDeregisterButton; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
if (button1.h == 0) |
{ |
GetControlBounds(control, &outRect); |
button1.v = outRect.top; |
button1.h = outRect.left; |
} |
button1.v += heighDiff; |
button1.h += widthDiff; |
MoveControl(control, button1.h, button1.v); |
} |
controlID.id = kServicesTypePopup; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
if (popup.h == 0) |
{ |
GetControlBounds(control, &outRect); |
popup.v = outRect.top; |
popup.h = outRect.left; |
} |
popup.h += widthDiff; |
MoveControl(control, popup.h, popup.v); |
} |
controlID.id = kServicesTypeText; |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
if (popuptext.h == 0) |
{ |
GetControlBounds(control, &outRect); |
popuptext.v = outRect.top; |
popuptext.h = outRect.left; |
} |
popuptext.h += widthDiff; |
MoveControl(control, popuptext.h, popuptext.v); |
} |
DrawControls(gMainWindow); |
} |
OSStatus |
MyWindowInterceptor(EventHandlerCallRef inCallRef, EventRef inEvent, void * inUserData) |
{ |
Rect previousBounds; |
Rect currentBounds; |
SInt16 heighDiff; |
SInt16 widthDiff; |
const Point minSize = { 320, 350 }; |
const Point maxSize = { 600, 600 }; |
OSStatus err1 = noErr; |
OSStatus err2 = noErr; |
switch (GetEventKind(inEvent)) |
{ |
case kEventWindowFocusAcquired: |
if (IsWindowVisible(gRegisterWindow) == false) DoActivateControls(); |
break; |
case kEventWindowFocusRelinquish: |
DoDeactivateControls(); |
break; |
case kEventWindowGetMinimumSize: |
err1 = SetEventParameter(inEvent, kEventParamDimensions, typeQDPoint, sizeof(minSize), &minSize); |
break; |
case kEventWindowGetMaximumSize: |
err1 = SetEventParameter(inEvent, kEventParamDimensions, typeQDPoint, sizeof(maxSize), &maxSize); |
break; |
case kEventWindowBoundsChanged: |
err1 = GetEventParameter(inEvent, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(currentBounds), NULL, ¤tBounds); |
err2 = GetEventParameter(inEvent, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(previousBounds), NULL, &previousBounds); |
if (err1 == noErr && err2 == noErr) |
{ |
heighDiff = (currentBounds.bottom - currentBounds.top) - (previousBounds.bottom - previousBounds.top); |
widthDiff = (currentBounds.right - currentBounds.left) - (previousBounds.right - previousBounds.left); |
// Only do stuff if the user actualy resized the window. |
if (heighDiff != 0 || widthDiff != 0) DoMoveControls(heighDiff, widthDiff); |
} |
break; |
} |
return ((err1 == noErr) ? err2 : err1); |
} |
void |
RefreshDataBrowserContent() |
{ |
UInt32 i; |
// This iterates through the currently opened neighborhoods to refresh the list. |
for (i = 0; i < kMaxNeighborhoods; i++) |
{ |
if (gNeighborhoodInfo.isDefaultNeighborhood[i] && gNeighborhoodInfo.isNeighborhoodOpen[i]) |
{ |
CancelLookups(i + 1); |
RemoveItemsFromList(i + 1); |
InstallEventLoopTimer(GetMainEventLoop(), 0.3, 0, gMyStartLookupTimerUPP, (void *)(i+1), NULL); |
} |
} |
} |
OSStatus |
MyPopupInterceptor(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData) |
{ |
static SInt16 menuItem = 0; |
switch ( GetEventKind(inEvent) ) |
{ |
case kEventMenuTargetItem: |
GetEventParameter(inEvent, kEventParamMenuItemIndex, typeMenuItemIndex, NULL, sizeof(typeMenuItemIndex), NULL, &menuItem); |
break; |
case kEventMenuEndTracking: |
if (menuItem != gPreviousItem && menuItem != 0) |
{ |
gPreviousItem = menuItem; |
SetServiceTypePopupMenu(menuItem); |
SetDataBrowserScrollPosition(gDataBrowserControl, 0 , 0); |
RefreshDataBrowserContent(); |
} |
break; |
} |
return noErr; |
} |
OSStatus |
MyRefreshBrowserTimer(EventLoopTimerRef inTimer, void * inUserData) |
{ |
UpdateItemCount(); |
return 0; |
} |
OSStatus |
MyAddItemInterceptor(EventHandlerCallRef inCallRef, EventRef inEvent, void * inUserData) |
{ |
DataBrowserItemID itemID; |
int isNeighborhood; |
char * name; |
EventTime startTime; |
OSStatus err = noErr; |
gEventHandled = true; |
startTime = GetCurrentEventTime(); |
err = MPWaitOnQueue(gQueue, (void **)&name, (void **)&itemID, (void **)&isNeighborhood, kDurationImmediate); |
while (err == noErr) |
{ |
if (isNeighborhood) |
{ |
if (itemID == kDefaultNeighborhoods) |
{ |
AddNeighborhoodToList(name, kDataBrowserNoItem); |
} |
else |
{ |
AddNeighborhoodToList(name, itemID); |
} |
} |
else |
{ |
AddServiceToList(name, itemID); |
} |
if ((GetCurrentEventTime() - startTime) > (kEventDurationMicrosecond * 10)) |
{ |
if (TestAndClear(7, &gEventHandled)) |
{ |
CreateAddItemEvent(); |
} |
break; |
} |
err = MPWaitOnQueue(gQueue, (void **)&name, (void **)&itemID, (void **)&isNeighborhood, kDurationImmediate); |
} |
return err; |
} |
static void |
DoAboutWindow() |
{ |
OSStatus err = noErr; |
Boolean result; |
result = MacIsWindowVisible(gAboutWindow); |
if (result == false) |
{ |
err = LoadAboutWindowFromNibFile(); |
if (err == noErr) |
{ |
RepositionWindow(gAboutWindow, gMainWindow, kWindowCenterOnParentWindow); |
BringToFront(gAboutWindow); |
ShowWindow(gAboutWindow); |
} |
} |
else |
{ |
SelectWindow(gAboutWindow); |
BringToFront(gAboutWindow); |
} |
} |
OSStatus |
MyCommandInterceptor(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData) |
{ |
HICommand theCommand; |
OSStatus err = noErr; |
err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &theCommand); |
if (err == noErr) |
{ |
switch (theCommand.commandID) |
{ |
case kShowRegisterEvent: |
err = LoadRegisterWindowFromNibFile(); |
if (err == noErr) ShowSheetWindow(gRegisterWindow, gMainWindow); |
break; |
case kDeregisterEvent: |
DoDeregisterURL(); |
break; |
case kHICommandAbout: |
DoAboutWindow(); |
break; |
default: |
CallNextEventHandler(inCallRef, inEvent); |
break; |
} |
} |
return err; |
} |
DEFINE_ONE_SHOT_HANDLER_GETTER(MyCommandInterceptor) |
DEFINE_ONE_SHOT_HANDLER_GETTER(MyWindowInterceptor) |
DEFINE_ONE_SHOT_HANDLER_GETTER(MyControlInterceptor) |
DEFINE_ONE_SHOT_HANDLER_GETTER(MyPopupInterceptor) |
DEFINE_ONE_SHOT_HANDLER_GETTER(MyAddItemInterceptor) |
OSStatus |
LoadMainWindowFromNibFile() |
{ |
ControlID controlID = { kNSLSample, kServicesTypePopup }; |
ControlRef control; |
MenuRef menuRef; |
CFBundleRef bundleRef; |
IBNibRef menuNibRef; |
OSStatus err = noErr; |
const EventTypeSpec commandEvents = { kEventClassCommand, kEventProcessCommand }; |
const EventTypeSpec addItemEvents = { kEventClassApplication, kAddItemToBrowser }; |
const EventTypeSpec menuEvents[] = { { kEventClassMenu, kEventMenuTargetItem }, { kEventClassMenu, kEventMenuEndTracking } }; |
const EventTypeSpec windowEvents[] = { { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassWindow, kEventWindowGetMinimumSize }, |
{ kEventClassWindow, kEventWindowGetMaximumSize }, { kEventClassWindow, kEventWindowFocusAcquired }, |
{ kEventClassWindow, kEventWindowFocusRelinquish } }; |
bundleRef = CFBundleGetMainBundle(); |
if (bundleRef) |
{ |
// Create a Nib reference passing the name of the nib file (without the .nib extension) |
if (gSystemIsMacOSX) err = CreateNibReferenceWithCFBundle(bundleRef, CFSTR("MenuX"), &menuNibRef); |
else err = CreateNibReferenceWithCFBundle(bundleRef, CFSTR("Menu9"), &menuNibRef); |
require_noerr( err, CantGetNibRef ); |
// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar |
// object. This name is set in InterfaceBuilder when the nib is created. |
err = SetMenuBarFromNib(menuNibRef, CFSTR("MainMenu")); |
require_noerr( err, CantSetMenuBar ); |
// Dispose the MenuBar nib. |
DisposeNibReference(menuNibRef); |
// Create a Nib reference passing the name of the nib file (without the .nib extension) |
err = CreateNibReferenceWithCFBundle(bundleRef, CFSTR("Main"), &gNibRef); |
require_noerr( err, CantGetNibRef ); |
// Then create a window. "MainWindow" is the name of the window object. This name is set in |
// InterfaceBuilder when the nib is created. |
err = CreateWindowFromNib(gNibRef, CFSTR("MainWindow"), &gMainWindow); |
require_noerr( err, CantCreateWindow ); |
// This will handle the About Box and the Register and Deregister buttons. |
InstallApplicationEventHandler(GetMyCommandInterceptorUPP(), 1, &commandEvents, NULL, NULL ); |
// This is used to add items to the Data Browser from the main thread. |
InstallApplicationEventHandler(GetMyAddItemInterceptorUPP(), 1, &addItemEvents, NULL, NULL ); |
// This handles resizing the window and disabling controls when the window is in the background. |
InstallWindowEventHandler(gMainWindow, GetMyWindowInterceptorUPP(), 5, windowEvents, NULL, NULL ); |
if (!gSystemIsMacOSX) |
{ |
// This will call YieldToAnyThread() when running on Mac OS 9 in order to give time to NSL. |
InstallEventLoopTimer(GetMainEventLoop(), kEventDurationForever, 50 * kEventDurationMillisecond, gMyYieldToAnyThreadTimerUPP, NULL, &gYieldTimerInfo.timerRef); |
} |
err = GetControlByID(gMainWindow, &controlID, &control); |
if (err == noErr) |
{ |
menuRef = GetControlPopupMenuHandle(control); |
if (menuRef) |
{ |
// This sets the value of the popup menu and refreshes the Data Browser when changed. |
InstallMenuEventHandler(menuRef, GetMyPopupInterceptorUPP(), 2, menuEvents, NULL, NULL); |
} |
} |
// Set up and show the Data Browser control. |
err = InitDataBrowserControl(); |
if (err == noErr) |
{ |
// This fires every second and checks if the Data Browser control needs to be redrawn. |
InstallEventLoopTimer(GetMainEventLoop(), kEventDurationNoWait, 1, gMyRefreshBrowserTimerUPP, NULL, NULL); |
} |
} |
CantGetNibRef: |
CantSetMenuBar: |
CantCreateWindow: |
return err; |
} |
OSStatus |
LoadRegisterWindowFromNibFile() |
{ |
ControlFontStyleRec fontRec; |
ControlID controlID = { kNSLSample, kRegisterAddressButton }; |
const EventTypeSpec buttonEvents = { kEventClassControl, kEventControlHit }; |
ControlRef control; |
OSStatus err = noErr; |
if (gRegisterWindow == NULL) |
{ |
// Then create a window. "gRegisterWindow" is the name of the window object. This name is set in |
// InterfaceBuilder when the nib is created. |
err = CreateWindowFromNib(gNibRef, CFSTR("RegisterWindow"), &gRegisterWindow); |
require_noerr(err, CantCreateWindow); |
controlID.id = kRegisterAddressButton; |
err = GetControlByID(gRegisterWindow, &controlID, &control); |
if (err == noErr) |
{ |
InstallControlEventHandler(control, GetMyControlInterceptorUPP(), 1, &buttonEvents, (void *) kRegisterAddressButton, NULL ); |
} |
controlID.id = kCancelRegisterButton; |
err = GetControlByID(gRegisterWindow, &controlID, &control); |
if (err == noErr) |
{ |
InstallControlEventHandler(control, GetMyControlInterceptorUPP(), 1, &buttonEvents, (void *) kCancelRegisterButton, NULL ); |
if (gSystemIsMacOSX) |
{ |
controlID.id = kRegisterInfoText; |
err = GetControlByID(gRegisterWindow, &controlID, &control); |
if (err == noErr) |
{ |
fontRec.flags = kControlUseFontMask | kControlUseFaceMask | kControlAddToMetaFontMask | kControlUseJustMask; |
fontRec.style = bold; |
fontRec.just = teJustLeft; |
fontRec.font = kControlFontBigSystemFont; |
SetControlFontStyle(control, &fontRec); |
} |
} |
} |
} |
ClearKeyboardFocus(gRegisterWindow); |
AdvanceKeyboardFocus(gRegisterWindow); |
CantCreateWindow: |
return err; |
} |
OSStatus |
LoadAboutWindowFromNibFile() |
{ |
ControlID controlID = { kNSLSample, kAboutAppNameText }; |
ControlRef control; |
ControlFontStyleRec fontRec; |
OSStatus err = noErr; |
// Then create a window. "gAboutWindow" is the name of the window object. This name is set in |
// InterfaceBuilder when the nib is created. |
if (gSystemIsMacOSX) err = CreateWindowFromNib(gNibRef, CFSTR("AboutWindowX"), &gAboutWindow); |
else err = CreateWindowFromNib(gNibRef, CFSTR("AboutWindow9"), &gAboutWindow); |
require_noerr(err, CantCreateWindow); |
err = GetControlByID(gAboutWindow, &controlID, &control); |
if (err == noErr) |
{ |
if (gSystemIsMacOSX) |
{ |
fontRec.flags = kControlUseFontMask | kControlUseFaceMask | kControlAddToMetaFontMask | kControlUseJustMask; |
fontRec.style = bold; |
} |
else |
{ |
fontRec.flags = kControlUseFontMask | kControlAddToMetaFontMask | kControlUseJustMask; |
} |
fontRec.just = teCenter; |
fontRec.font = kControlFontBigSystemFont; |
SetControlFontStyle(control, &fontRec); |
SetControlData(control, kControlNoPart, kControlEditTextTextTag, strlen(kAppName), kAppName); |
} |
controlID.id = kAboutVersionText; |
err = GetControlByID(gAboutWindow, &controlID, &control); |
if (err == noErr) |
{ |
fontRec.flags = kControlUseFontMask | kControlAddToMetaFontMask | kControlUseJustMask; |
fontRec.just = teCenter; |
fontRec.font = kControlFontSmallSystemFont; |
SetControlFontStyle(control, &fontRec); |
SetControlData(control, kControlNoPart, kControlEditTextTextTag, strlen(kAppVersion), kAppVersion); |
} |
CantCreateWindow: |
return err; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14