jdk/src/macosx/native/sun/awt/CPrinterJob.m
changeset 12047 320a714614e9
child 15639 0ff6be5c9730
equal deleted inserted replaced
12046:378aa3362868 12047:320a714614e9
       
     1 /*
       
     2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 
       
    27 #import "java_awt_print_PageFormat.h"
       
    28 #import "java_awt_print_Pageable.h"
       
    29 #import "sun_lwawt_macosx_CPrinterJob.h"
       
    30 #import "sun_lwawt_macosx_CPrinterPageDialog.h"
       
    31 
       
    32 #import <Cocoa/Cocoa.h>
       
    33 #import <JavaNativeFoundation/JavaNativeFoundation.h>
       
    34 
       
    35 #import "PrinterView.h"
       
    36 #import "PrintModel.h"
       
    37 #import "ThreadUtilities.h"
       
    38 #import "GeomUtilities.h"
       
    39 
       
    40 static JNF_CLASS_CACHE(sjc_Paper, "java/awt/print/Paper");
       
    41 static JNF_CLASS_CACHE(sjc_PageFormat, "java/awt/print/PageFormat");
       
    42 static JNF_CLASS_CACHE(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob");
       
    43 static JNF_CLASS_CACHE(sjc_CPrinterDialog, "sun/lwawt/macosx/CPrinterDialog");
       
    44 static JNF_MEMBER_CACHE(sjm_getNSPrintInfo, sjc_CPrinterJob, "getNSPrintInfo", "()J");
       
    45 static JNF_MEMBER_CACHE(sjm_printerJob, sjc_CPrinterDialog, "fPrinterJob", "Lsun/lwawt/macosx/CPrinterJob;");
       
    46 
       
    47 static NSPrintInfo* createDefaultNSPrintInfo();
       
    48 
       
    49 static void makeBestFit(NSPrintInfo* src);
       
    50 
       
    51 static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst);
       
    52 static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst);
       
    53 
       
    54 static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst);
       
    55 static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageFormat, NSPrintInfo* dst);
       
    56 
       
    57 static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable);
       
    58 static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst);
       
    59 
       
    60 
       
    61 static NSPrintInfo* createDefaultNSPrintInfo(JNIEnv* env, jstring printer)
       
    62 {
       
    63     NSPrintInfo* defaultPrintInfo = [[NSPrintInfo sharedPrintInfo] copy];
       
    64     if (printer != NULL)
       
    65     {
       
    66         NSPrinter* nsPrinter = [NSPrinter printerWithName:JNFJavaToNSString(env, printer)];
       
    67         if (nsPrinter != nil)
       
    68         {
       
    69             [defaultPrintInfo setPrinter:nsPrinter];
       
    70         }
       
    71     }
       
    72     [defaultPrintInfo setUpPrintOperationDefaultValues];
       
    73 
       
    74     // cmc 05/18/04 radr://3160443 : setUpPrintOperationDefaultValues sets the
       
    75     // page margins to 72, 72, 90, 90 - need to use [NSPrintInfo imageablePageBounds]
       
    76     // to get values from the printer.
       
    77     // NOTE: currently [NSPrintInfo imageablePageBounds] does not update itself when
       
    78     // the user selects a different printer - see radr://3657453. However, rather than
       
    79     // directly querying the PPD here, we'll let AppKit printing do the work. The AppKit
       
    80     // printing bug above is set to be fixed for Tiger.
       
    81     NSRect imageableRect = [defaultPrintInfo imageablePageBounds];
       
    82     [defaultPrintInfo setLeftMargin: imageableRect.origin.x];
       
    83     [defaultPrintInfo setBottomMargin: imageableRect.origin.y]; //top and bottom are flipped because [NSPrintInfo imageablePageBounds] returns a flipped NSRect (bottom-left to top-right).
       
    84     [defaultPrintInfo setRightMargin: [defaultPrintInfo paperSize].width-imageableRect.origin.x-imageableRect.size.width];
       
    85     [defaultPrintInfo setTopMargin: [defaultPrintInfo paperSize].height-imageableRect.origin.y-imageableRect.size.height];
       
    86 
       
    87     return defaultPrintInfo;
       
    88 }
       
    89 
       
    90 static void makeBestFit(NSPrintInfo* src)
       
    91 {
       
    92     // This will look at the NSPrintInfo's margins. If they are out of bounds to the
       
    93     // imageable area of the page, it will set them to the largest possible size.
       
    94 
       
    95     NSRect imageable = [src imageablePageBounds];
       
    96 
       
    97     NSSize paperSize = [src paperSize];
       
    98 
       
    99     CGFloat fullLeftM = imageable.origin.x;
       
   100     CGFloat fullRightM = paperSize.width - (imageable.origin.x + imageable.size.width);
       
   101 
       
   102     // These are flipped because [NSPrintInfo imageablePageBounds] returns a flipped
       
   103     //  NSRect (bottom-left to top-right).
       
   104     CGFloat fullTopM = paperSize.height - (imageable.origin.y + imageable.size.height);
       
   105     CGFloat fullBottomM = imageable.origin.y;
       
   106 
       
   107     if (fullLeftM > [src leftMargin])
       
   108     {
       
   109         [src setLeftMargin:fullLeftM];
       
   110     }
       
   111 
       
   112     if (fullRightM > [src rightMargin])
       
   113     {
       
   114         [src setRightMargin:fullRightM];
       
   115     }
       
   116 
       
   117     if (fullTopM > [src topMargin])
       
   118     {
       
   119         [src setTopMargin:fullTopM];
       
   120     }
       
   121 
       
   122     if (fullBottomM > [src bottomMargin])
       
   123     {
       
   124         [src setBottomMargin:fullBottomM];
       
   125     }
       
   126 }
       
   127 
       
   128 // In AppKit Printing, the rectangle is always oriented. In AppKit Printing, setting
       
   129 //  the rectangle will always set the orientation.
       
   130 // In java printing, the rectangle is oriented if accessed from PageFormat. It is
       
   131 //  not oriented when accessed from Paper.
       
   132 
       
   133 static void nsPrintInfoToJavaPaper(JNIEnv* env, NSPrintInfo* src, jobject dst)
       
   134 {
       
   135     static JNF_MEMBER_CACHE(jm_setSize, sjc_Paper, "setSize", "(DD)V");
       
   136     static JNF_MEMBER_CACHE(jm_setImageableArea, sjc_Paper, "setImageableArea", "(DDDD)V");
       
   137 
       
   138     jdouble jPaperW, jPaperH;
       
   139 
       
   140     // NSPrintInfo paperSize is oriented. java Paper is not oriented. Take
       
   141     //  the -[NSPrintInfo orientation] into account when setting the Paper
       
   142     //  rectangle.
       
   143 
       
   144     NSSize paperSize = [src paperSize];
       
   145     switch ([src orientation]) {
       
   146         case NSPortraitOrientation:
       
   147             jPaperW = paperSize.width;
       
   148             jPaperH = paperSize.height;
       
   149             break;
       
   150 
       
   151         case NSLandscapeOrientation:
       
   152             jPaperW = paperSize.height;
       
   153             jPaperH = paperSize.width;
       
   154             break;
       
   155 
       
   156         default:
       
   157             jPaperW = paperSize.width;
       
   158             jPaperH = paperSize.height;
       
   159             break;
       
   160     }
       
   161 
       
   162     JNFCallVoidMethod(env, dst, jm_setSize, jPaperW, jPaperH); // AWT_THREADING Safe (known object - always actual Paper)
       
   163 
       
   164     // Set the imageable area from the margins
       
   165     CGFloat leftM = [src leftMargin];
       
   166     CGFloat rightM = [src rightMargin];
       
   167     CGFloat topM = [src topMargin];
       
   168     CGFloat bottomM = [src bottomMargin];
       
   169 
       
   170     jdouble jImageX = leftM;
       
   171     jdouble jImageY = topM;
       
   172     jdouble jImageW = jPaperW - (leftM + rightM);
       
   173     jdouble jImageH = jPaperH - (topM + bottomM);
       
   174 
       
   175     JNFCallVoidMethod(env, dst, jm_setImageableArea, jImageX, jImageY, jImageW, jImageH); // AWT_THREADING Safe (known object - always actual Paper)
       
   176 }
       
   177 
       
   178 static void javaPaperToNSPrintInfo(JNIEnv* env, jobject src, NSPrintInfo* dst)
       
   179 {
       
   180     AWT_ASSERT_NOT_APPKIT_THREAD;
       
   181 
       
   182     static JNF_MEMBER_CACHE(jm_getWidth, sjc_Paper, "getWidth", "()D");
       
   183     static JNF_MEMBER_CACHE(jm_getHeight, sjc_Paper, "getHeight", "()D");
       
   184     static JNF_MEMBER_CACHE(jm_getImageableX, sjc_Paper, "getImageableX", "()D");
       
   185     static JNF_MEMBER_CACHE(jm_getImageableY, sjc_Paper, "getImageableY", "()D");
       
   186     static JNF_MEMBER_CACHE(jm_getImageableW, sjc_Paper, "getImageableWidth", "()D");
       
   187     static JNF_MEMBER_CACHE(jm_getImageableH, sjc_Paper, "getImageableHeight", "()D");
       
   188 
       
   189     // java Paper is always Portrait oriented. Set NSPrintInfo with this
       
   190     //  rectangle, and it's orientation may change. If necessary, be sure to call
       
   191     //  -[NSPrintInfo setOrientation] after this call, which will then
       
   192     //  adjust the -[NSPrintInfo paperSize] as well.
       
   193 
       
   194     jdouble jPhysicalWidth = JNFCallDoubleMethod(env, src, jm_getWidth); // AWT_THREADING Safe (!appKit)
       
   195     jdouble jPhysicalHeight = JNFCallDoubleMethod(env, src, jm_getHeight); // AWT_THREADING Safe (!appKit)
       
   196 
       
   197     [dst setPaperSize:NSMakeSize(jPhysicalWidth, jPhysicalHeight)];
       
   198 
       
   199     // Set the margins from the imageable area
       
   200     jdouble jImageX = JNFCallDoubleMethod(env, src, jm_getImageableX); // AWT_THREADING Safe (!appKit)
       
   201     jdouble jImageY = JNFCallDoubleMethod(env, src, jm_getImageableY); // AWT_THREADING Safe (!appKit)
       
   202     jdouble jImageW = JNFCallDoubleMethod(env, src, jm_getImageableW); // AWT_THREADING Safe (!appKit)
       
   203     jdouble jImageH = JNFCallDoubleMethod(env, src, jm_getImageableH); // AWT_THREADING Safe (!appKit)
       
   204 
       
   205     [dst setLeftMargin:(CGFloat)jImageX];
       
   206     [dst setTopMargin:(CGFloat)jImageY];
       
   207     [dst setRightMargin:(CGFloat)(jPhysicalWidth - jImageW - jImageX)];
       
   208     [dst setBottomMargin:(CGFloat)(jPhysicalHeight - jImageH - jImageY)];
       
   209 }
       
   210 
       
   211 static void nsPrintInfoToJavaPageFormat(JNIEnv* env, NSPrintInfo* src, jobject dst)
       
   212 {
       
   213     AWT_ASSERT_NOT_APPKIT_THREAD;
       
   214 
       
   215     static JNF_MEMBER_CACHE(jm_setOrientation, sjc_PageFormat, "setOrientation", "(I)V");
       
   216     static JNF_MEMBER_CACHE(jm_setPaper, sjc_PageFormat, "setPaper", "(Ljava/awt/print/Paper;)V");
       
   217     static JNF_CTOR_CACHE(jm_Paper_ctor, sjc_Paper, "()V");
       
   218 
       
   219     jint jOrientation;
       
   220     NSPrintingOrientation nsOrientation = [src orientation];
       
   221     switch (nsOrientation) {
       
   222         case NSPortraitOrientation:
       
   223             jOrientation = java_awt_print_PageFormat_PORTRAIT;
       
   224             break;
       
   225 
       
   226         case NSLandscapeOrientation:
       
   227             jOrientation = java_awt_print_PageFormat_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
       
   228             break;
       
   229 
       
   230 /*
       
   231         // AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295.
       
   232         case NSReverseLandscapeOrientation:
       
   233             jOrientation = java_awt_print_PageFormat.REVERSE_LANDSCAPE; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
       
   234             break;
       
   235 */
       
   236 
       
   237         default:
       
   238             jOrientation = java_awt_print_PageFormat_PORTRAIT;
       
   239             break;
       
   240     }
       
   241 
       
   242     JNFCallVoidMethod(env, dst, jm_setOrientation, jOrientation); // AWT_THREADING Safe (!appKit)
       
   243 
       
   244     // Create a new Paper
       
   245     jobject paper = JNFNewObject(env, jm_Paper_ctor); // AWT_THREADING Safe (known object)
       
   246 
       
   247     nsPrintInfoToJavaPaper(env, src, paper);
       
   248 
       
   249     // Set the Paper in the PageFormat
       
   250     JNFCallVoidMethod(env, dst, jm_setPaper, paper); // AWT_THREADING Safe (!appKit)
       
   251 
       
   252     (*env)->DeleteLocalRef(env, paper);
       
   253 }
       
   254 
       
   255 static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobject srcPageFormat, NSPrintInfo* dstPrintInfo)
       
   256 {
       
   257     AWT_ASSERT_NOT_APPKIT_THREAD;
       
   258 
       
   259     static JNF_MEMBER_CACHE(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I");
       
   260     static JNF_MEMBER_CACHE(jm_getPaper, sjc_PageFormat, "getPaper", "()Ljava/awt/print/Paper;");
       
   261     static JNF_MEMBER_CACHE(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;");
       
   262 
       
   263     // When setting page information (orientation, size) in NSPrintInfo, set the
       
   264     //  rectangle first. This is because setting the orientation will change the
       
   265     //  rectangle to match.
       
   266 
       
   267     // Set up the paper. This will force Portrait since java Paper is
       
   268     //  not oriented. Then setting the NSPrintInfo orientation below
       
   269     //  will flip NSPrintInfo's info as necessary.
       
   270     jobject paper = JNFCallObjectMethod(env, srcPageFormat, jm_getPaper); // AWT_THREADING Safe (!appKit)
       
   271     javaPaperToNSPrintInfo(env, paper, dstPrintInfo);
       
   272     (*env)->DeleteLocalRef(env, paper);
       
   273 
       
   274     switch (JNFCallIntMethod(env, srcPageFormat, jm_getOrientation)) { // AWT_THREADING Safe (!appKit)
       
   275         case java_awt_print_PageFormat_PORTRAIT:
       
   276             [dstPrintInfo setOrientation:NSPortraitOrientation];
       
   277             break;
       
   278 
       
   279         case java_awt_print_PageFormat_LANDSCAPE:
       
   280             [dstPrintInfo setOrientation:NSLandscapeOrientation]; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
       
   281             break;
       
   282 
       
   283         // AppKit printing doesn't support REVERSE_LANDSCAPE. Radar 2960295.
       
   284         case java_awt_print_PageFormat_REVERSE_LANDSCAPE:
       
   285             [dstPrintInfo setOrientation:NSLandscapeOrientation]; //+++gdb Are LANDSCAPE and REVERSE_LANDSCAPE still inverted?
       
   286             break;
       
   287 
       
   288         default:
       
   289             [dstPrintInfo setOrientation:NSPortraitOrientation];
       
   290             break;
       
   291     }
       
   292 
       
   293     // <rdar://problem/4022422> NSPrinterInfo is not correctly set to the selected printer
       
   294     // from the Java side of CPrinterJob. Has always assumed the default printer was the one we wanted.
       
   295     if (srcPrintJob == NULL) return;
       
   296     jobject printerNameObj = JNFCallObjectMethod(env, srcPrintJob, jm_getPrinterName);
       
   297     if (printerNameObj == NULL) return;
       
   298     NSString *printerName = JNFJavaToNSString(env, printerNameObj);
       
   299     if (printerName == nil) return;
       
   300     NSPrinter *printer = [NSPrinter printerWithName:printerName];
       
   301     if (printer == nil) return;
       
   302     [dstPrintInfo setPrinter:printer];
       
   303 }
       
   304 
       
   305 static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable)
       
   306 {
       
   307     static JNF_MEMBER_CACHE(jm_setService, sjc_CPrinterJob, "setPrinterServiceFromNative", "(Ljava/lang/String;)V");
       
   308     static JNF_MEMBER_CACHE(jm_setCopies, sjc_CPrinterJob, "setCopies", "(I)V");
       
   309     static JNF_MEMBER_CACHE(jm_setCollated, sjc_CPrinterJob, "setCollated", "(Z)V");
       
   310     static JNF_MEMBER_CACHE(jm_setPageRange, sjc_CPrinterJob, "setPageRange", "(II)V");
       
   311 
       
   312     // get the selected printer's name, and set the appropriate PrintService on the Java side
       
   313     NSString *name = [[src printer] name];
       
   314     jstring printerName = JNFNSToJavaString(env, name);
       
   315     JNFCallVoidMethod(env, dstPrinterJob, jm_setService, printerName);
       
   316 
       
   317 
       
   318     NSMutableDictionary* printingDictionary = [src dictionary];
       
   319 
       
   320     NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies];
       
   321     if ([nsCopies respondsToSelector:@selector(integerValue)])
       
   322     {
       
   323         JNFCallVoidMethod(env, dstPrinterJob, jm_setCopies, [nsCopies integerValue]); // AWT_THREADING Safe (known object)
       
   324     }
       
   325 
       
   326     NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate];
       
   327     if ([nsCollated respondsToSelector:@selector(boolValue)])
       
   328     {
       
   329         JNFCallVoidMethod(env, dstPrinterJob, jm_setCollated, [nsCollated boolValue] ? JNI_TRUE : JNI_FALSE); // AWT_THREADING Safe (known object)
       
   330     }
       
   331 
       
   332     NSNumber* nsPrintAllPages = [printingDictionary objectForKey:NSPrintAllPages];
       
   333     if ([nsPrintAllPages respondsToSelector:@selector(boolValue)])
       
   334     {
       
   335         jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES;
       
   336         if (![nsPrintAllPages boolValue])
       
   337         {
       
   338             NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage];
       
   339             if ([nsFirstPage respondsToSelector:@selector(integerValue)])
       
   340             {
       
   341                 jFirstPage = [nsFirstPage integerValue] - 1;
       
   342             }
       
   343 
       
   344             NSNumber* nsLastPage = [printingDictionary objectForKey:NSPrintLastPage];
       
   345             if ([nsLastPage respondsToSelector:@selector(integerValue)])
       
   346             {
       
   347                 jLastPage = [nsLastPage integerValue] - 1;
       
   348             }
       
   349         }
       
   350 
       
   351         JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRange, jFirstPage, jLastPage); // AWT_THREADING Safe (known object)
       
   352     }
       
   353 }
       
   354 
       
   355 static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobject srcPageable, NSPrintInfo* dst)
       
   356 {
       
   357     AWT_ASSERT_NOT_APPKIT_THREAD;
       
   358 
       
   359     static JNF_CLASS_CACHE(jc_Pageable, "java/awt/print/Pageable");
       
   360     static JNF_MEMBER_CACHE(jm_getCopies, sjc_CPrinterJob, "getCopiesInt", "()I");
       
   361     static JNF_MEMBER_CACHE(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z");
       
   362     static JNF_MEMBER_CACHE(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I");
       
   363 
       
   364     NSMutableDictionary* printingDictionary = [dst dictionary];
       
   365 
       
   366     jint copies = JNFCallIntMethod(env, srcPrinterJob, jm_getCopies); // AWT_THREADING Safe (known object)
       
   367     [printingDictionary setObject:[NSNumber numberWithInteger:copies] forKey:NSPrintCopies];
       
   368 
       
   369     jboolean collated = JNFCallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object)
       
   370     [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate];
       
   371 
       
   372     jint jNumPages = JNFCallIntMethod(env, srcPageable, jm_getNumberOfPages); // AWT_THREADING Safe (!appKit)
       
   373     if (jNumPages != java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES)
       
   374     {
       
   375         [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages];
       
   376 
       
   377         [printingDictionary setObject:[NSNumber numberWithInteger:1] forKey:NSPrintFirstPage];
       
   378         [printingDictionary setObject:[NSNumber numberWithInteger:jNumPages] forKey:NSPrintLastPage];
       
   379     }
       
   380     else
       
   381     {
       
   382         [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages];
       
   383     }
       
   384 }
       
   385 
       
   386 /*
       
   387  * Class:     sun_lwawt_macosx_EventDispatchAccess
       
   388  * Method:    pumpEventsAndWait
       
   389  * Signature: ()V
       
   390  */
       
   391 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_EventDispatchAccess_pumpEventsAndWait
       
   392 (JNIEnv *env, jobject eda)
       
   393 {
       
   394     static JNF_CLASS_CACHE(jc_Thread, "java/lang/Thread");
       
   395     static JNF_STATIC_MEMBER_CACHE(jm_currentThread, jc_Thread, "currentThread", "()Ljava/lang/Thread;");
       
   396     static JNF_CLASS_CACHE(jc_EventDispatchThread, "java/awt/EventDispatchThread");
       
   397     static JNF_MEMBER_CACHE(jm_macosxGetConditional, jc_EventDispatchThread, "_macosxGetConditional", "(Ljava/lang/Object;)Ljava/awt/Conditional;");
       
   398     static JNF_MEMBER_CACHE(jm_pumpEvents, jc_EventDispatchThread, "pumpEvents", "(Ljava/awt/Conditional;)V");
       
   399 
       
   400 JNF_COCOA_DURING(env);
       
   401 
       
   402     jobject thread = JNFCallStaticObjectMethod(env, jm_currentThread);
       
   403     jobject conditional = JNFCallObjectMethod(env, thread, jm_macosxGetConditional, eda);
       
   404     if (conditional != NULL) {
       
   405         JNFCallVoidMethod(env, thread, jm_pumpEvents, conditional);
       
   406     }
       
   407 
       
   408 JNF_COCOA_HANDLE(env);
       
   409 }
       
   410 
       
   411 /*
       
   412  * Class:     sun_lwawt_macosx_CPrinterJob
       
   413  * Method:    abortDoc
       
   414  * Signature: ()V
       
   415  */
       
   416 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_abortDoc
       
   417   (JNIEnv *env, jobject jthis)
       
   418 {
       
   419 JNF_COCOA_ENTER(env);
       
   420     // This is only called during the printLoop from the printLoop thread
       
   421     NSPrintOperation* printLoop = [NSPrintOperation currentOperation];
       
   422     NSPrintInfo* printInfo = [printLoop printInfo];
       
   423     [printInfo setJobDisposition:NSPrintCancelJob];
       
   424 JNF_COCOA_EXIT(env);
       
   425 }
       
   426 
       
   427 /*
       
   428  * Class:     sun_lwawt_macosx_CPrinterJob
       
   429  * Method:    getDefaultPage
       
   430  * Signature: (Ljava/awt/print/PageFormat;)V
       
   431  */
       
   432 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_getDefaultPage
       
   433   (JNIEnv *env, jobject jthis, jobject page)
       
   434 {
       
   435 JNF_COCOA_ENTER(env);
       
   436     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
       
   437 
       
   438     nsPrintInfoToJavaPageFormat(env, printInfo, page);
       
   439 
       
   440     [printInfo release];
       
   441 JNF_COCOA_EXIT(env);
       
   442 }
       
   443 
       
   444 /*
       
   445  * Class:     sun_lwawt_macosx_CPrinterJob
       
   446  * Method:    validatePaper
       
   447  * Signature: (Ljava/awt/print/Paper;Ljava/awt/print/Paper;)V
       
   448  */
       
   449 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_validatePaper
       
   450   (JNIEnv *env, jobject jthis, jobject origpaper, jobject newpaper)
       
   451 {
       
   452 JNF_COCOA_ENTER(env);
       
   453 
       
   454     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
       
   455     javaPaperToNSPrintInfo(env, origpaper, printInfo);
       
   456     makeBestFit(printInfo);
       
   457     nsPrintInfoToJavaPaper(env, printInfo, newpaper);
       
   458     [printInfo release];
       
   459 
       
   460 JNF_COCOA_EXIT(env);
       
   461 }
       
   462 
       
   463 /*
       
   464  * Class:     sun_lwawt_macosx_CPrinterJob
       
   465  * Method:    createNSPrintInfo
       
   466  * Signature: ()J
       
   467  */
       
   468 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CPrinterJob_createNSPrintInfo
       
   469   (JNIEnv *env, jobject jthis)
       
   470 {
       
   471     jlong result = -1;
       
   472 JNF_COCOA_ENTER(env);
       
   473     // This is used to create the NSPrintInfo for this PrinterJob. Thread
       
   474     //  safety is assured by the java side of this call.
       
   475 
       
   476     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
       
   477     if (printInfo) CFRetain(printInfo); // GC
       
   478     [printInfo release];
       
   479 
       
   480     result = ptr_to_jlong(printInfo);
       
   481 
       
   482 JNF_COCOA_EXIT(env);
       
   483     return result;
       
   484 }
       
   485 
       
   486 /*
       
   487  * Class:     sun_lwawt_macosx_CPrinterJob
       
   488  * Method:    dispose
       
   489  * Signature: (J)V
       
   490  */
       
   491 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPrinterJob_dispose
       
   492   (JNIEnv *env, jobject jthis, jlong nsPrintInfo)
       
   493 {
       
   494 JNF_COCOA_ENTER(env);
       
   495     if (nsPrintInfo != -1)
       
   496     {
       
   497         NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo);
       
   498         if (printInfo) CFRelease(printInfo); // GC
       
   499     }
       
   500 JNF_COCOA_EXIT(env);
       
   501 }
       
   502 
       
   503 
       
   504 /*
       
   505  * Class:     sun_lwawt_macosx_CPrinterJob
       
   506  * Method:    printLoop
       
   507  * Signature: ()V
       
   508  */
       
   509 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJob_printLoop
       
   510   (JNIEnv *env, jobject jthis, jboolean blocks, jint firstPage, jint lastPage)
       
   511 {
       
   512     AWT_ASSERT_NOT_APPKIT_THREAD;
       
   513 
       
   514     static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormat", "(I)Ljava/awt/print/PageFormat;");
       
   515     static JNF_MEMBER_CACHE(jm_getPageFormatArea, sjc_CPrinterJob, "getPageFormatArea", "(Ljava/awt/print/PageFormat;)Ljava/awt/geom/Rectangle2D;");
       
   516     static JNF_MEMBER_CACHE(jm_getPrinterName, sjc_CPrinterJob, "getPrinterName", "()Ljava/lang/String;");
       
   517     static JNF_MEMBER_CACHE(jm_getPageable, sjc_CPrinterJob, "getPageable", "()Ljava/awt/print/Pageable;");
       
   518 
       
   519     jboolean retVal = JNI_FALSE;
       
   520 
       
   521 JNF_COCOA_ENTER(env);
       
   522     // Get the first page's PageFormat for setting things up (This introduces
       
   523     //  and is a facet of the same problem in Radar 2818593/2708932).
       
   524     jobject page = JNFCallObjectMethod(env, jthis, jm_getPageFormat, 0); // AWT_THREADING Safe (!appKit)
       
   525     if (page != NULL) {
       
   526         jobject pageFormatArea = JNFCallObjectMethod(env, jthis, jm_getPageFormatArea, page); // AWT_THREADING Safe (!appKit)
       
   527 
       
   528         PrinterView* printerView = [[PrinterView alloc] initWithFrame:JavaToNSRect(env, pageFormatArea) withEnv:env withPrinterJob:jthis];
       
   529         [printerView setFirstPage:firstPage lastPage:lastPage];
       
   530 
       
   531         NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(JNFCallLongMethod(env, jthis, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
       
   532 
       
   533         // <rdar://problem/4156975> passing jthis CPrinterJob as well, so we can extract the printer name from the current job
       
   534         javaPageFormatToNSPrintInfo(env, jthis, page, printInfo);
       
   535 
       
   536         // <rdar://problem/4093799> NSPrinterInfo is not correctly set to the selected printer
       
   537         // from the Java side of CPrinterJob. Had always assumed the default printer was the one we wanted.
       
   538         jobject printerNameObj = JNFCallObjectMethod(env, jthis, jm_getPrinterName);
       
   539         if (printerNameObj != NULL) {
       
   540             NSString *printerName = JNFJavaToNSString(env, printerNameObj);
       
   541             if (printerName != nil) {
       
   542                 NSPrinter *printer = [NSPrinter printerWithName:printerName];
       
   543                 if (printer != nil) [printInfo setPrinter:printer];
       
   544             }
       
   545         }
       
   546 
       
   547         // <rdar://problem/4367998> JTable.print attributes are ignored
       
   548         jobject pageable = JNFCallObjectMethod(env, jthis, jm_getPageable); // AWT_THREADING Safe (!appKit)
       
   549         javaPrinterJobToNSPrintInfo(env, jthis, pageable, printInfo);
       
   550 
       
   551         PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
       
   552 
       
   553         (void)[printModel runPrintLoopWithView:printerView waitUntilDone:blocks withEnv:env];
       
   554 
       
   555         // Only set this if we got far enough to call runPrintLoopWithView, or we will spin CPrinterJob.print() forever!
       
   556         retVal = JNI_TRUE;
       
   557 
       
   558         [printModel release];
       
   559         [printerView release];
       
   560 
       
   561         if (page != NULL)
       
   562         {
       
   563             (*env)->DeleteLocalRef(env, page);
       
   564         }
       
   565 
       
   566         if (pageFormatArea != NULL)
       
   567         {
       
   568             (*env)->DeleteLocalRef(env, pageFormatArea);
       
   569         }
       
   570     }
       
   571 JNF_COCOA_EXIT(env);
       
   572     return retVal;
       
   573 }
       
   574 
       
   575 /*
       
   576  * Class:     sun_lwawt_macosx_CPrinterPageDialog
       
   577  * Method:    showDialog
       
   578  * Signature: ()Z
       
   579  */
       
   580 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterPageDialog_showDialog
       
   581   (JNIEnv *env, jobject jthis)
       
   582 {
       
   583 
       
   584     static JNF_CLASS_CACHE(jc_CPrinterPageDialog, "sun/lwawt/macosx/CPrinterPageDialog");
       
   585     static JNF_MEMBER_CACHE(jm_page, jc_CPrinterPageDialog, "fPage", "Ljava/awt/print/PageFormat;");
       
   586 
       
   587     jboolean result = JNI_FALSE;
       
   588 JNF_COCOA_ENTER(env);
       
   589     jobject printerJob = JNFGetObjectField(env, jthis, sjm_printerJob);
       
   590     NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(JNFCallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
       
   591 
       
   592     jobject page = JNFGetObjectField(env, jthis, jm_page);
       
   593 
       
   594     // <rdar://problem/4156975> passing NULL, because only a CPrinterJob has a real printer associated with it
       
   595     javaPageFormatToNSPrintInfo(env, NULL, page, printInfo);
       
   596 
       
   597     PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
       
   598     result = [printModel runPageSetup];
       
   599     [printModel release];
       
   600 
       
   601     if (result)
       
   602     {
       
   603         nsPrintInfoToJavaPageFormat(env, printInfo, page);
       
   604     }
       
   605 
       
   606     if (printerJob != NULL)
       
   607     {
       
   608         (*env)->DeleteLocalRef(env, printerJob);
       
   609     }
       
   610 
       
   611     if (page != NULL)
       
   612     {
       
   613         (*env)->DeleteLocalRef(env, page);
       
   614     }
       
   615 
       
   616 JNF_COCOA_EXIT(env);
       
   617     return result;
       
   618 }
       
   619 
       
   620 /*
       
   621  * Class:     sun_lwawt_macosx_CPrinterJobDialog
       
   622  * Method:    showDialog
       
   623  * Signature: ()Z
       
   624  */
       
   625 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPrinterJobDialog_showDialog
       
   626   (JNIEnv *env, jobject jthis)
       
   627 {
       
   628     static JNF_CLASS_CACHE(jc_CPrinterJobDialog, "sun/lwawt/macosx/CPrinterJobDialog");
       
   629     static JNF_MEMBER_CACHE(jm_pageable, jc_CPrinterJobDialog, "fPageable", "Ljava/awt/print/Pageable;");
       
   630 
       
   631     jboolean result = JNI_FALSE;
       
   632 JNF_COCOA_ENTER(env);
       
   633     jobject printerJob = JNFGetObjectField(env, jthis, sjm_printerJob);
       
   634     NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(JNFCallLongMethod(env, printerJob, sjm_getNSPrintInfo)); // AWT_THREADING Safe (known object)
       
   635 
       
   636     jobject pageable = JNFGetObjectField(env, jthis, jm_pageable);
       
   637 
       
   638     javaPrinterJobToNSPrintInfo(env, printerJob, pageable, printInfo);
       
   639 
       
   640     PrintModel* printModel = [[PrintModel alloc] initWithPrintInfo:printInfo];
       
   641     result = [printModel runJobSetup];
       
   642     [printModel release];
       
   643 
       
   644     if (result)
       
   645     {
       
   646         nsPrintInfoToJavaPrinterJob(env, printInfo, printerJob, pageable);
       
   647     }
       
   648 
       
   649     if (printerJob != NULL)
       
   650     {
       
   651         (*env)->DeleteLocalRef(env, printerJob);
       
   652     }
       
   653 
       
   654     if (pageable != NULL)
       
   655     {
       
   656         (*env)->DeleteLocalRef(env, pageable);
       
   657     }
       
   658 
       
   659 JNF_COCOA_EXIT(env);
       
   660     return result;
       
   661 }