blob: c1e1dc7459d85c54c646430ca4bc4c294d133266 [file] [log] [blame]
reed@android.com33469852008-12-18 03:41:19 +00001/*
2
3File: main.c
4
5Abstract: Main event loop and app handling code is found in here.
6
7Version: 1.0
8
9� Copyright 2005 Apple Computer, Inc. All rights reserved.
10
11IMPORTANT: This Apple software is supplied to
12you by Apple Computer, Inc. ("Apple") in
13consideration of your agreement to the following
14terms, and your use, installation, modification
15or redistribution of this Apple software
16constitutes acceptance of these terms. If you do
17not agree with these terms, please do not use,
18install, modify or redistribute this Apple
19software.
20
21In consideration of your agreement to abide by
22the following terms, and subject to these terms,
23Apple grants you a personal, non-exclusive
24license, under Apple's copyrights in this
25original Apple software (the "Apple Software"),
26to use, reproduce, modify and redistribute the
27Apple Software, with or without modifications, in
28source and/or binary forms; provided that if you
29redistribute the Apple Software in its entirety
30and without modifications, you must retain this
31notice and the following text and disclaimers in
32all such redistributions of the Apple Software.
33Neither the name, trademarks, service marks or
34logos of Apple Computer, Inc. may be used to
35endorse or promote products derived from the
36Apple Software without specific prior written
37permission from Apple. Except as expressly
38stated in this notice, no other rights or
39licenses, express or implied, are granted by
40Apple herein, including but not limited to any
41patent rights that may be infringed by your
42derivative works or by other works in which the
43Apple Software may be incorporated.
44
45The Apple Software is provided by Apple on an "AS
46IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR
47IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
48WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY
49AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
50THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE
51OR IN COMBINATION WITH YOUR PRODUCTS.
52
53IN NO EVENT SHALL APPLE BE LIABLE FOR ANY
54SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
55DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
57OF USE, DATA, OR PROFITS; OR BUSINESS
58INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
59REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF
60THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER
61UNDER THEORY OF CONTRACT, TORT (INCLUDING
62NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN
63IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
64SUCH DAMAGE.
65
66*/
67
68
69#include <Carbon/Carbon.h>
70#include "CIDraw.h"
71
72/* Constants */
73#define kMyHIViewSignature 'ciHV'
74#define kMyHIViewFieldID 128
75#define kGammaSliderSignature 'gSLD'
76#define kGammaSliderFieldID 128
77#define kAboutBoxStringKey CFSTR("AboutString") // these key the localizable strings
78
79/* Private Prototypes */
80static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler, EventRef event, void *userData);
81static void MyGammaSliderProc( ControlHandle control, SInt16 part );
82static pascal OSStatus DoAppCommandProcess(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
83static PMPageFormat CreateDefaultPageFormat(void);
84static OSStatus DoPageSetup(PMPageFormat pageFormat);
85static OSStatus DoPrint(PMPageFormat pageFormat);
86static OSStatus MyDoPrintLoop(PMPrintSession printSession, PMPageFormat pageFormat, PMPrintSettings printSettings);
87static void DoAboutBox();
88
89/* Global Data */
90static HIViewRef gMyHIView = NULL;
91static HIViewRef gGammaSliderView = NULL;
92static PMPageFormat gPageFormat = NULL;
93
94int main(int argc, char* argv[])
95{
96 static const HIViewID kMyViewID = {kMyHIViewSignature, kMyHIViewFieldID };
97 static const HIViewID kGammaSliderID = {kGammaSliderSignature, kGammaSliderFieldID };
98
99 IBNibRef nibRef;
100 WindowRef window;
101 EventTargetRef myEventTarget;
102 static const EventTypeSpec kMyViewEvents[] = {kEventClassControl, kEventControlDraw };
103 static const EventTypeSpec kMyCommandEvents[] = {kEventClassCommand, kEventCommandProcess };
104 OSStatus err = noErr;
105
106 // Create a Nib reference passing the name of the nib file (without the .nib extension)
107 // CreateNibReference only searches into the application bundle.
108 err = CreateNibReference(CFSTR("main"), &nibRef);
109 require_noerr( err, CantGetNibRef );
110
111 // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
112 // object. This name is set in InterfaceBuilder when the nib is created.
113 err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
114 require_noerr( err, CantSetMenuBar );
115
116 // Then create a window. "MainWindow" is the name of the window object. This name is set in
117 // InterfaceBuilder when the nib is created.
118 err = CreateWindowFromNib(nibRef, CFSTR("MainWindow"), &window);
119 require_noerr( err, CantCreateWindow );
120 // Get the HIView associated with the window.
121 HIViewFindByID( HIViewGetRoot( window ), kMyViewID, &gMyHIView );
122
123 // make the view opaque
124 HIViewChangeFeatures(gMyHIView, kHIViewIsOpaque, 0);
125
126 // Get the event target for the view.
127 myEventTarget = GetControlEventTarget (gMyHIView);
128
129 // Install the event handler for the HIView.
130 err = InstallEventHandler (myEventTarget,
131 NewEventHandlerUPP (MyDrawEventHandler),
132 GetEventTypeCount(kMyViewEvents),
133 kMyViewEvents,
134 (void *) gMyHIView,
135 NULL);
136
137
138 HIViewFindByID( HIViewGetRoot( window ), kGammaSliderID, &gGammaSliderView );
139 SetControlAction( gGammaSliderView, NewControlActionUPP(MyGammaSliderProc) );
140
141 // Install the handler for the menu commands.
142 InstallApplicationEventHandler(NewEventHandlerUPP(DoAppCommandProcess), GetEventTypeCount(kMyCommandEvents),
143 kMyCommandEvents, NULL, NULL);
144
145
146 // We don't need the nib reference anymore.
147 DisposeNibReference(nibRef);
148
149 // The window was created hidden so show it.
150 ShowWindow( window );
151
152 // Call the event loop
153 RunApplicationEventLoop();
154
155CantCreateWindow:
156CantSetMenuBar:
157CantGetNibRef:
158 return err;
159}
160
161static const void* myGetBytesPointer(void* info) {
162 return info;
163}
164
165static void myReleaseBytePointer(void* info, const void* pointer) {
166 pointer = 0;
167}
168
169static size_t myGetBytesAtPosition(void* info, void* buffer, off_t pos, size_t count) {
170 memcpy(buffer, (const char*)info + pos, count);
171 return count;
172}
173
174static void myReleaseInfo(void* info) {
175}
176
177static void TestDraw(CGContextRef cg, CGRect bounds) {
178 const int w = 64;
179 const int h = 64;
180 uint32_t data[w*h];
181 int i;
182 for (i = 0; i < w*h; i++) {
183 data[i] = 0x00008888;
184 }
185 CGDataProviderDirectCallbacks procs;
186 procs.version = 0;
187 procs.getBytePointer = myGetBytesPointer;
188 procs.releaseBytePointer = myReleaseBytePointer;
189 procs.getBytesAtPosition = myGetBytesAtPosition;
190 procs.releaseInfo = myReleaseInfo;
191
192 CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
193
194 size_t size = w * h * 4;
195 CGDataProviderRef dataRef = CGDataProviderCreateDirect(data, size, &procs);
196 CGImageRef ref = CGImageCreate(w, h, 8, 32, w*4,
197 space,
198 kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast,
199 dataRef,
200 NULL,
201 false,
202 kCGRenderingIntentDefault);
203
204 CGColorSpaceRelease(space);
205 CGDataProviderRelease(dataRef);
206
207 CGRect r = CGRectMake(0, 0, w, h);
208 CGContextDrawImage(cg, r, ref);
209 CGImageRelease(ref);
210}
211
212static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler, EventRef event, void *userData)
213{
214 // NOTE: GState is save/restored by the HIView system doing the callback, so the draw handler doesn't need to do it
215
216 OSStatus status = noErr;
217 CGContextRef context;
218 HIRect bounds;
219
220 // Get the CGContextRef
221 status = GetEventParameter (event, kEventParamCGContextRef,
222 typeCGContextRef, NULL,
223 sizeof (CGContextRef),
224 NULL,
225 &context);
226
227 if(status != noErr){
228 fprintf(stderr, "Got error %d getting the context!\n", status);
229 return status;
230 }
231
232 // Get the bounding rectangle
233 HIViewGetBounds ((HIViewRef) userData, &bounds);
234
235 // Flip the coordinates by translating and scaling. This produces a
236 // coordinate system that matches the Quartz default coordinate system
237 // with the origin in the lower-left corner with the y axis pointing up.
238
239// CGContextTranslateCTM (context, 0, bounds.size.height);
240// CGContextScaleCTM (context, 1.0, -1.0);
241
242// DoDraw(context, bounds);
243 TestDraw(context, bounds);
244 return status;
245
246}
247
248static void MyGammaSliderProc( ControlHandle control, SInt16 part )
249{
250 gGammaValue = GetControl32BitValue(control);
251 HIViewSetNeedsDisplay(gMyHIView, true);
252 HIViewRender(gMyHIView);
253}
254
255
256// Handle command-process events at the application level
257static pascal OSStatus DoAppCommandProcess(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
258{
259#pragma unused (nextHandler, userData)
260 HICommand aCommand;
261 OSStatus result = eventNotHandledErr;
262
263 GetEventParameter(theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &aCommand);
264
265 switch (aCommand.commandID)
266 {
267
268 case kHICommandPageSetup:
269 if(gPageFormat == NULL)
270 gPageFormat = CreateDefaultPageFormat();
271
272 if(gPageFormat)
273 (void)DoPageSetup(gPageFormat);
274
275 result = noErr;
276 break;
277
278 case kHICommandPrint:
279 if(gPageFormat == NULL)
280 gPageFormat = CreateDefaultPageFormat();
281
282 if(gPageFormat)
283 (void)DoPrint(gPageFormat);
284
285 result = noErr;
286 break;
287
288 case kHICommandAbout:
289 DoAboutBox();
290 result = noErr;
291 break;
292
293 default:
294 break;
295
296 case kHICommandQuit:
297 QuitApplicationEventLoop();
298 result = noErr;
299 break;
300 }
301 HiliteMenu(0);
302 return result;
303}
304
305static void DoAboutBox()
306{
307 CFStringRef outString = NULL;
308 SInt16 alertItemHit = 0;
309 Str255 stringBuf;
310
311 outString = CFCopyLocalizedString(kAboutBoxStringKey, NULL);
312 if (outString != NULL)
313 {
314 if (CFStringGetPascalString (outString, stringBuf, sizeof(stringBuf), GetApplicationTextEncoding()))
315 {
316 StandardAlert(kAlertStopAlert, stringBuf, NULL, NULL, &alertItemHit);
317 }
318 CFRelease (outString);
319 }
320}
321
322// -----------------------------------------------------------------------
323static PMPageFormat CreateDefaultPageFormat(void)
324{
325 OSStatus err = noErr, tempErr;
326 PMPageFormat pageFormat = NULL;
327 PMPrintSession printSession;
328 err = PMCreateSession(&printSession);
329 if(!err){
330 err = PMCreatePageFormat(&pageFormat); // we own a reference to this page format
331 if(err == noErr)
332 err = PMSessionDefaultPageFormat(printSession, pageFormat);
333
334 tempErr = PMRelease(printSession);
335 if(!err)err = tempErr;
336 }
337 if(err){
338 fprintf(stderr, "got an error = %d creating the default page format\n", err);
339 }
340 return pageFormat;
341}
342
343// -----------------------------------------------------------------
344static OSStatus DoPageSetup(PMPageFormat pageFormat)
345{
346 OSStatus err = noErr;
347 PMPrintSession printSession;
348 err = PMCreateSession(&printSession);
349 if(!err){
350 Boolean accepted;
351 if(!err) // validate the page format we're going to pass to the dialog code
352 err = PMSessionValidatePageFormat(printSession, pageFormat, kPMDontWantBoolean);
353 if(!err){
354 err = PMSessionPageSetupDialog(printSession, pageFormat, &accepted);
355 }
356 (void)PMRelease(printSession);
357 }
358
359 if(err && err != kPMCancel)
360 fprintf(stderr, "Got an error %d in Page Setup\n", err);
361
362 return err;
363} // DoPageSetup
364
365// -------------------------------------------------------------------------------
366static OSStatus DoPrint(PMPageFormat pageFormat)
367{
368 OSStatus err = noErr;
369 UInt32 minPage = 1, maxPage = 1;
370 PMPrintSession printSession;
371 err = PMCreateSession(&printSession);
372 if(err == noErr){
373 // validate the page format we're going to use
374 err = PMSessionValidatePageFormat(printSession,
375 pageFormat,
376 kPMDontWantBoolean);
377 if (err == noErr)
378 {
379 PMPrintSettings printSettings = NULL;
380 err = PMCreatePrintSettings(&printSettings);
381 if(err == noErr)
382 err = PMSessionDefaultPrintSettings(printSession, printSettings);
383
384 if (err == noErr)
385 err = PMSetPageRange(printSettings, minPage, maxPage);
386
387 if (err == noErr)
388 {
389 Boolean accepted;
390 err = PMSessionPrintDialog(printSession, printSettings,
391 pageFormat,
392 &accepted);
393 if(accepted){
394 err = MyDoPrintLoop(printSession, pageFormat, printSettings);
395 }
396 }
397 if(printSettings)
398 (void)PMRelease(printSettings);
399 }
400
401 (void)PMRelease(printSession); // ignoring error since we already have one
402 }
403
404 if(err && err != kPMCancel)
405 fprintf(stderr, "Got an error %d in Print\n", err);
406 return err;
407}
408
409// --------------------------------------------------------------------------------------
410static OSStatus MyDoPrintLoop(PMPrintSession printSession, PMPageFormat pageFormat, PMPrintSettings printSettings)
411{
412 OSStatus err = noErr;
413 OSStatus tempErr = noErr;
414 UInt32 firstPage, lastPage, totalDocPages = 1;
415
416 if(!err)
417 err = PMGetFirstPage(printSettings, &firstPage);
418
419 if (!err)
420 err = PMGetLastPage(printSettings, &lastPage);
421
422 if(!err && lastPage > totalDocPages){
423 // don't draw more than the number of pages in our document
424 lastPage = totalDocPages;
425 }
426
427 if (!err) // tell the printing system the number of pages we are going to print
428 err = PMSetLastPage(printSettings, lastPage, false);
429
430 if (!err)
431 {
432 err = PMSessionBeginCGDocument(printSession, printSettings, pageFormat);
433 if (!err){
434 UInt32 pageNumber = firstPage;
435 // need to check errors from our print loop and errors from the session for each
436 // time around our print loop before calling our BeginPageProc
437 while(pageNumber <= lastPage && err == noErr && PMSessionError(printSession) == noErr)
438 {
439 err = PMSessionBeginPage(printSession, pageFormat, NULL);
440 if (!err){
441 CGContextRef printingContext = NULL;
442 err = PMSessionGetCGGraphicsContext(printSession, &printingContext);
443 if(!err){
444 PMRect pageRect;
445
446 PMGetAdjustedPaperRect(pageFormat, &pageRect);
447 DoDraw(printingContext, CGRectMake(pageRect.left, pageRect.top, pageRect.right - pageRect.left, pageRect.bottom - pageRect.top));
448 }
449 // we must call EndPage if BeginPage returned noErr
450 tempErr = PMSessionEndPage(printSession);
451
452 if(!err)err = tempErr;
453 }
454 pageNumber++;
455 } // end while loop
456
457 // we must call EndDocument if BeginDocument returned noErr
458 tempErr = PMSessionEndDocument(printSession);
459
460 if(!err)err = tempErr;
461 if(!err)
462 err = PMSessionError(printSession);
463 }
464 }
465 return err;
466}
467
468
469