| /* |
| |
| File: main.c |
| |
| Abstract: Main event loop and app handling code is found in here. |
| |
| Version: 1.0 |
| |
| � Copyright 2005 Apple Computer, Inc. All rights reserved. |
| |
| 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. |
| |
| */ |
| |
| |
| #include <Carbon/Carbon.h> |
| #include "CIDraw.h" |
| |
| /* Constants */ |
| #define kMyHIViewSignature 'ciHV' |
| #define kMyHIViewFieldID 128 |
| #define kGammaSliderSignature 'gSLD' |
| #define kGammaSliderFieldID 128 |
| #define kAboutBoxStringKey CFSTR("AboutString") // these key the localizable strings |
| |
| /* Private Prototypes */ |
| static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler, EventRef event, void *userData); |
| static void MyGammaSliderProc( ControlHandle control, SInt16 part ); |
| static pascal OSStatus DoAppCommandProcess(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); |
| static PMPageFormat CreateDefaultPageFormat(void); |
| static OSStatus DoPageSetup(PMPageFormat pageFormat); |
| static OSStatus DoPrint(PMPageFormat pageFormat); |
| static OSStatus MyDoPrintLoop(PMPrintSession printSession, PMPageFormat pageFormat, PMPrintSettings printSettings); |
| static void DoAboutBox(); |
| |
| /* Global Data */ |
| static HIViewRef gMyHIView = NULL; |
| static HIViewRef gGammaSliderView = NULL; |
| static PMPageFormat gPageFormat = NULL; |
| |
| int main(int argc, char* argv[]) |
| { |
| static const HIViewID kMyViewID = {kMyHIViewSignature, kMyHIViewFieldID }; |
| static const HIViewID kGammaSliderID = {kGammaSliderSignature, kGammaSliderFieldID }; |
| |
| IBNibRef nibRef; |
| WindowRef window; |
| EventTargetRef myEventTarget; |
| static const EventTypeSpec kMyViewEvents[] = {kEventClassControl, kEventControlDraw }; |
| static const EventTypeSpec kMyCommandEvents[] = {kEventClassCommand, kEventCommandProcess }; |
| OSStatus err = noErr; |
| |
| // Create a Nib reference passing the name of the nib file (without the .nib extension) |
| // CreateNibReference only searches into the application bundle. |
| err = CreateNibReference(CFSTR("main"), &nibRef); |
| 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(nibRef, CFSTR("MenuBar")); |
| require_noerr( err, CantSetMenuBar ); |
| |
| // 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(nibRef, CFSTR("MainWindow"), &window); |
| require_noerr( err, CantCreateWindow ); |
| // Get the HIView associated with the window. |
| HIViewFindByID( HIViewGetRoot( window ), kMyViewID, &gMyHIView ); |
| |
| // make the view opaque |
| HIViewChangeFeatures(gMyHIView, kHIViewIsOpaque, 0); |
| |
| // Get the event target for the view. |
| myEventTarget = GetControlEventTarget (gMyHIView); |
| |
| // Install the event handler for the HIView. |
| err = InstallEventHandler (myEventTarget, |
| NewEventHandlerUPP (MyDrawEventHandler), |
| GetEventTypeCount(kMyViewEvents), |
| kMyViewEvents, |
| (void *) gMyHIView, |
| NULL); |
| |
| |
| HIViewFindByID( HIViewGetRoot( window ), kGammaSliderID, &gGammaSliderView ); |
| SetControlAction( gGammaSliderView, NewControlActionUPP(MyGammaSliderProc) ); |
| |
| // Install the handler for the menu commands. |
| InstallApplicationEventHandler(NewEventHandlerUPP(DoAppCommandProcess), GetEventTypeCount(kMyCommandEvents), |
| kMyCommandEvents, NULL, NULL); |
| |
| |
| // We don't need the nib reference anymore. |
| DisposeNibReference(nibRef); |
| |
| // The window was created hidden so show it. |
| ShowWindow( window ); |
| |
| // Call the event loop |
| RunApplicationEventLoop(); |
| |
| CantCreateWindow: |
| CantSetMenuBar: |
| CantGetNibRef: |
| return err; |
| } |
| |
| static const void* myGetBytesPointer(void* info) { |
| return info; |
| } |
| |
| static void myReleaseBytePointer(void* info, const void* pointer) { |
| pointer = 0; |
| } |
| |
| static size_t myGetBytesAtPosition(void* info, void* buffer, off_t pos, size_t count) { |
| memcpy(buffer, (const char*)info + pos, count); |
| return count; |
| } |
| |
| static void myReleaseInfo(void* info) { |
| } |
| |
| static void TestDraw(CGContextRef cg, CGRect bounds) { |
| const int w = 64; |
| const int h = 64; |
| uint32_t data[w*h]; |
| int i; |
| for (i = 0; i < w*h; i++) { |
| data[i] = 0x00008888; |
| } |
| CGDataProviderDirectCallbacks procs; |
| procs.version = 0; |
| procs.getBytePointer = myGetBytesPointer; |
| procs.releaseBytePointer = myReleaseBytePointer; |
| procs.getBytesAtPosition = myGetBytesAtPosition; |
| procs.releaseInfo = myReleaseInfo; |
| |
| CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); |
| |
| size_t size = w * h * 4; |
| CGDataProviderRef dataRef = CGDataProviderCreateDirect(data, size, &procs); |
| CGImageRef ref = CGImageCreate(w, h, 8, 32, w*4, |
| space, |
| kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast, |
| dataRef, |
| NULL, |
| false, |
| kCGRenderingIntentDefault); |
| |
| CGColorSpaceRelease(space); |
| CGDataProviderRelease(dataRef); |
| |
| CGRect r = CGRectMake(0, 0, w, h); |
| CGContextDrawImage(cg, r, ref); |
| CGImageRelease(ref); |
| } |
| |
| static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler, EventRef event, void *userData) |
| { |
| // NOTE: GState is save/restored by the HIView system doing the callback, so the draw handler doesn't need to do it |
| |
| OSStatus status = noErr; |
| CGContextRef context; |
| HIRect bounds; |
| |
| // Get the CGContextRef |
| status = GetEventParameter (event, kEventParamCGContextRef, |
| typeCGContextRef, NULL, |
| sizeof (CGContextRef), |
| NULL, |
| &context); |
| |
| if(status != noErr){ |
| fprintf(stderr, "Got error %d getting the context!\n", status); |
| return status; |
| } |
| |
| // Get the bounding rectangle |
| HIViewGetBounds ((HIViewRef) userData, &bounds); |
| |
| // Flip the coordinates by translating and scaling. This produces a |
| // coordinate system that matches the Quartz default coordinate system |
| // with the origin in the lower-left corner with the y axis pointing up. |
| |
| // CGContextTranslateCTM (context, 0, bounds.size.height); |
| // CGContextScaleCTM (context, 1.0, -1.0); |
| |
| // DoDraw(context, bounds); |
| TestDraw(context, bounds); |
| return status; |
| |
| } |
| |
| static void MyGammaSliderProc( ControlHandle control, SInt16 part ) |
| { |
| gGammaValue = GetControl32BitValue(control); |
| HIViewSetNeedsDisplay(gMyHIView, true); |
| HIViewRender(gMyHIView); |
| } |
| |
| |
| // Handle command-process events at the application level |
| static pascal OSStatus DoAppCommandProcess(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) |
| { |
| #pragma unused (nextHandler, userData) |
| HICommand aCommand; |
| OSStatus result = eventNotHandledErr; |
| |
| GetEventParameter(theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &aCommand); |
| |
| switch (aCommand.commandID) |
| { |
| |
| case kHICommandPageSetup: |
| if(gPageFormat == NULL) |
| gPageFormat = CreateDefaultPageFormat(); |
| |
| if(gPageFormat) |
| (void)DoPageSetup(gPageFormat); |
| |
| result = noErr; |
| break; |
| |
| case kHICommandPrint: |
| if(gPageFormat == NULL) |
| gPageFormat = CreateDefaultPageFormat(); |
| |
| if(gPageFormat) |
| (void)DoPrint(gPageFormat); |
| |
| result = noErr; |
| break; |
| |
| case kHICommandAbout: |
| DoAboutBox(); |
| result = noErr; |
| break; |
| |
| default: |
| break; |
| |
| case kHICommandQuit: |
| QuitApplicationEventLoop(); |
| result = noErr; |
| break; |
| } |
| HiliteMenu(0); |
| return result; |
| } |
| |
| static void DoAboutBox() |
| { |
| CFStringRef outString = NULL; |
| SInt16 alertItemHit = 0; |
| Str255 stringBuf; |
| |
| outString = CFCopyLocalizedString(kAboutBoxStringKey, NULL); |
| if (outString != NULL) |
| { |
| if (CFStringGetPascalString (outString, stringBuf, sizeof(stringBuf), GetApplicationTextEncoding())) |
| { |
| StandardAlert(kAlertStopAlert, stringBuf, NULL, NULL, &alertItemHit); |
| } |
| CFRelease (outString); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| static PMPageFormat CreateDefaultPageFormat(void) |
| { |
| OSStatus err = noErr, tempErr; |
| PMPageFormat pageFormat = NULL; |
| PMPrintSession printSession; |
| err = PMCreateSession(&printSession); |
| if(!err){ |
| err = PMCreatePageFormat(&pageFormat); // we own a reference to this page format |
| if(err == noErr) |
| err = PMSessionDefaultPageFormat(printSession, pageFormat); |
| |
| tempErr = PMRelease(printSession); |
| if(!err)err = tempErr; |
| } |
| if(err){ |
| fprintf(stderr, "got an error = %d creating the default page format\n", err); |
| } |
| return pageFormat; |
| } |
| |
| // ----------------------------------------------------------------- |
| static OSStatus DoPageSetup(PMPageFormat pageFormat) |
| { |
| OSStatus err = noErr; |
| PMPrintSession printSession; |
| err = PMCreateSession(&printSession); |
| if(!err){ |
| Boolean accepted; |
| if(!err) // validate the page format we're going to pass to the dialog code |
| err = PMSessionValidatePageFormat(printSession, pageFormat, kPMDontWantBoolean); |
| if(!err){ |
| err = PMSessionPageSetupDialog(printSession, pageFormat, &accepted); |
| } |
| (void)PMRelease(printSession); |
| } |
| |
| if(err && err != kPMCancel) |
| fprintf(stderr, "Got an error %d in Page Setup\n", err); |
| |
| return err; |
| } // DoPageSetup |
| |
| // ------------------------------------------------------------------------------- |
| static OSStatus DoPrint(PMPageFormat pageFormat) |
| { |
| OSStatus err = noErr; |
| UInt32 minPage = 1, maxPage = 1; |
| PMPrintSession printSession; |
| err = PMCreateSession(&printSession); |
| if(err == noErr){ |
| // validate the page format we're going to use |
| err = PMSessionValidatePageFormat(printSession, |
| pageFormat, |
| kPMDontWantBoolean); |
| if (err == noErr) |
| { |
| PMPrintSettings printSettings = NULL; |
| err = PMCreatePrintSettings(&printSettings); |
| if(err == noErr) |
| err = PMSessionDefaultPrintSettings(printSession, printSettings); |
| |
| if (err == noErr) |
| err = PMSetPageRange(printSettings, minPage, maxPage); |
| |
| if (err == noErr) |
| { |
| Boolean accepted; |
| err = PMSessionPrintDialog(printSession, printSettings, |
| pageFormat, |
| &accepted); |
| if(accepted){ |
| err = MyDoPrintLoop(printSession, pageFormat, printSettings); |
| } |
| } |
| if(printSettings) |
| (void)PMRelease(printSettings); |
| } |
| |
| (void)PMRelease(printSession); // ignoring error since we already have one |
| } |
| |
| if(err && err != kPMCancel) |
| fprintf(stderr, "Got an error %d in Print\n", err); |
| return err; |
| } |
| |
| // -------------------------------------------------------------------------------------- |
| static OSStatus MyDoPrintLoop(PMPrintSession printSession, PMPageFormat pageFormat, PMPrintSettings printSettings) |
| { |
| OSStatus err = noErr; |
| OSStatus tempErr = noErr; |
| UInt32 firstPage, lastPage, totalDocPages = 1; |
| |
| if(!err) |
| err = PMGetFirstPage(printSettings, &firstPage); |
| |
| if (!err) |
| err = PMGetLastPage(printSettings, &lastPage); |
| |
| if(!err && lastPage > totalDocPages){ |
| // don't draw more than the number of pages in our document |
| lastPage = totalDocPages; |
| } |
| |
| if (!err) // tell the printing system the number of pages we are going to print |
| err = PMSetLastPage(printSettings, lastPage, false); |
| |
| if (!err) |
| { |
| err = PMSessionBeginCGDocument(printSession, printSettings, pageFormat); |
| if (!err){ |
| UInt32 pageNumber = firstPage; |
| // need to check errors from our print loop and errors from the session for each |
| // time around our print loop before calling our BeginPageProc |
| while(pageNumber <= lastPage && err == noErr && PMSessionError(printSession) == noErr) |
| { |
| err = PMSessionBeginPage(printSession, pageFormat, NULL); |
| if (!err){ |
| CGContextRef printingContext = NULL; |
| err = PMSessionGetCGGraphicsContext(printSession, &printingContext); |
| if(!err){ |
| PMRect pageRect; |
| |
| PMGetAdjustedPaperRect(pageFormat, &pageRect); |
| DoDraw(printingContext, CGRectMake(pageRect.left, pageRect.top, pageRect.right - pageRect.left, pageRect.bottom - pageRect.top)); |
| } |
| // we must call EndPage if BeginPage returned noErr |
| tempErr = PMSessionEndPage(printSession); |
| |
| if(!err)err = tempErr; |
| } |
| pageNumber++; |
| } // end while loop |
| |
| // we must call EndDocument if BeginDocument returned noErr |
| tempErr = PMSessionEndDocument(printSession); |
| |
| if(!err)err = tempErr; |
| if(!err) |
| err = PMSessionError(printSession); |
| } |
| } |
| return err; |
| } |
| |
| |
| |