Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/native/common/awt/CUPSfuncs.c
41153 views
1
/*
2
* Copyright (c) 2003, 2020, 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
#include <jni.h>
27
#include <jni_util.h>
28
#include <jvm_md.h>
29
#include <dlfcn.h>
30
#include <cups/cups.h>
31
#include <cups/ppd.h>
32
33
34
//#define CUPS_DEBUG
35
36
#ifdef CUPS_DEBUG
37
#define DPRINTF(x, y) fprintf(stderr, x, y);
38
#else
39
#define DPRINTF(x, y)
40
#endif
41
42
typedef const char* (*fn_cupsServer)(void);
43
typedef int (*fn_ippPort)(void);
44
typedef http_t* (*fn_httpConnect)(const char *, int);
45
typedef void (*fn_httpClose)(http_t *);
46
typedef char* (*fn_cupsGetPPD)(const char *);
47
typedef cups_dest_t* (*fn_cupsGetDest)(const char *name,
48
const char *instance, int num_dests, cups_dest_t *dests);
49
typedef int (*fn_cupsGetDests)(cups_dest_t **dests);
50
typedef void (*fn_cupsFreeDests)(int num_dests, cups_dest_t *dests);
51
typedef ppd_file_t* (*fn_ppdOpenFile)(const char *);
52
typedef void (*fn_ppdClose)(ppd_file_t *);
53
typedef ppd_option_t* (*fn_ppdFindOption)(ppd_file_t *, const char *);
54
typedef ppd_size_t* (*fn_ppdPageSize)(ppd_file_t *, char *);
55
56
fn_cupsServer j2d_cupsServer;
57
fn_ippPort j2d_ippPort;
58
fn_httpConnect j2d_httpConnect;
59
fn_httpClose j2d_httpClose;
60
fn_cupsGetPPD j2d_cupsGetPPD;
61
fn_cupsGetDest j2d_cupsGetDest;
62
fn_cupsGetDests j2d_cupsGetDests;
63
fn_cupsFreeDests j2d_cupsFreeDests;
64
fn_ppdOpenFile j2d_ppdOpenFile;
65
fn_ppdClose j2d_ppdClose;
66
fn_ppdFindOption j2d_ppdFindOption;
67
fn_ppdPageSize j2d_ppdPageSize;
68
69
70
/*
71
* Initialize library functions.
72
* // REMIND : move tab , add dlClose before return
73
*/
74
JNIEXPORT jboolean JNICALL
75
Java_sun_print_CUPSPrinter_initIDs(JNIEnv *env,
76
jobject printObj) {
77
void *handle = dlopen(VERSIONED_JNI_LIB_NAME("cups", "2"),
78
RTLD_LAZY | RTLD_GLOBAL);
79
80
if (handle == NULL) {
81
handle = dlopen(JNI_LIB_NAME("cups"), RTLD_LAZY | RTLD_GLOBAL);
82
if (handle == NULL) {
83
return JNI_FALSE;
84
}
85
}
86
87
j2d_cupsServer = (fn_cupsServer)dlsym(handle, "cupsServer");
88
if (j2d_cupsServer == NULL) {
89
dlclose(handle);
90
return JNI_FALSE;
91
}
92
93
j2d_ippPort = (fn_ippPort)dlsym(handle, "ippPort");
94
if (j2d_ippPort == NULL) {
95
dlclose(handle);
96
return JNI_FALSE;
97
}
98
99
j2d_httpConnect = (fn_httpConnect)dlsym(handle, "httpConnect");
100
if (j2d_httpConnect == NULL) {
101
dlclose(handle);
102
return JNI_FALSE;
103
}
104
105
j2d_httpClose = (fn_httpClose)dlsym(handle, "httpClose");
106
if (j2d_httpClose == NULL) {
107
dlclose(handle);
108
return JNI_FALSE;
109
}
110
111
j2d_cupsGetPPD = (fn_cupsGetPPD)dlsym(handle, "cupsGetPPD");
112
if (j2d_cupsGetPPD == NULL) {
113
dlclose(handle);
114
return JNI_FALSE;
115
}
116
117
j2d_cupsGetDest = (fn_cupsGetDest)dlsym(handle, "cupsGetDest");
118
if (j2d_cupsGetDest == NULL) {
119
dlclose(handle);
120
return JNI_FALSE;
121
}
122
123
j2d_cupsGetDests = (fn_cupsGetDests)dlsym(handle, "cupsGetDests");
124
if (j2d_cupsGetDests == NULL) {
125
dlclose(handle);
126
return JNI_FALSE;
127
}
128
129
j2d_cupsFreeDests = (fn_cupsFreeDests)dlsym(handle, "cupsFreeDests");
130
if (j2d_cupsFreeDests == NULL) {
131
dlclose(handle);
132
return JNI_FALSE;
133
}
134
135
j2d_ppdOpenFile = (fn_ppdOpenFile)dlsym(handle, "ppdOpenFile");
136
if (j2d_ppdOpenFile == NULL) {
137
dlclose(handle);
138
return JNI_FALSE;
139
140
}
141
142
j2d_ppdClose = (fn_ppdClose)dlsym(handle, "ppdClose");
143
if (j2d_ppdClose == NULL) {
144
dlclose(handle);
145
return JNI_FALSE;
146
147
}
148
149
j2d_ppdFindOption = (fn_ppdFindOption)dlsym(handle, "ppdFindOption");
150
if (j2d_ppdFindOption == NULL) {
151
dlclose(handle);
152
return JNI_FALSE;
153
}
154
155
j2d_ppdPageSize = (fn_ppdPageSize)dlsym(handle, "ppdPageSize");
156
if (j2d_ppdPageSize == NULL) {
157
dlclose(handle);
158
return JNI_FALSE;
159
}
160
161
return JNI_TRUE;
162
}
163
164
/*
165
* Gets CUPS server name.
166
*
167
*/
168
JNIEXPORT jstring JNICALL
169
Java_sun_print_CUPSPrinter_getCupsServer(JNIEnv *env,
170
jobject printObj)
171
{
172
jstring cServer = NULL;
173
const char* server = j2d_cupsServer();
174
if (server != NULL) {
175
// Is this a local domain socket?
176
if (strncmp(server, "/", 1) == 0) {
177
cServer = JNU_NewStringPlatform(env, "localhost");
178
} else {
179
cServer = JNU_NewStringPlatform(env, server);
180
}
181
}
182
return cServer;
183
}
184
185
/*
186
* Gets CUPS port name.
187
*
188
*/
189
JNIEXPORT jint JNICALL
190
Java_sun_print_CUPSPrinter_getCupsPort(JNIEnv *env,
191
jobject printObj)
192
{
193
int port = j2d_ippPort();
194
return (jint) port;
195
}
196
197
198
/*
199
* Gets CUPS default printer name.
200
*
201
*/
202
JNIEXPORT jstring JNICALL
203
Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env,
204
jobject printObj)
205
{
206
jstring cDefPrinter = NULL;
207
cups_dest_t *dests;
208
char *defaultPrinter = NULL;
209
int num_dests = j2d_cupsGetDests(&dests);
210
int i = 0;
211
cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests);
212
if (dest != NULL) {
213
defaultPrinter = dest->name;
214
if (defaultPrinter != NULL) {
215
cDefPrinter = JNU_NewStringPlatform(env, defaultPrinter);
216
}
217
}
218
j2d_cupsFreeDests(num_dests, dests);
219
return cDefPrinter;
220
}
221
222
/*
223
* Checks if connection can be made to the server.
224
*
225
*/
226
JNIEXPORT jboolean JNICALL
227
Java_sun_print_CUPSPrinter_canConnect(JNIEnv *env,
228
jobject printObj,
229
jstring server,
230
jint port)
231
{
232
const char *serverName;
233
serverName = (*env)->GetStringUTFChars(env, server, NULL);
234
if (serverName != NULL) {
235
http_t *http = j2d_httpConnect(serverName, (int)port);
236
(*env)->ReleaseStringUTFChars(env, server, serverName);
237
if (http != NULL) {
238
j2d_httpClose(http);
239
return JNI_TRUE;
240
}
241
}
242
return JNI_FALSE;
243
}
244
245
246
/*
247
* Returns list of media: pages + trays
248
*/
249
JNIEXPORT jobjectArray JNICALL
250
Java_sun_print_CUPSPrinter_getMedia(JNIEnv *env,
251
jobject printObj,
252
jstring printer)
253
{
254
ppd_file_t *ppd;
255
ppd_option_t *optionTray, *optionPage;
256
ppd_choice_t *choice;
257
const char *name;
258
const char *filename;
259
int i, nTrays=0, nPages=0, nTotal=0;
260
jstring utf_str;
261
jclass cls;
262
jobjectArray nameArray = NULL;
263
264
name = (*env)->GetStringUTFChars(env, printer, NULL);
265
if (name == NULL) {
266
(*env)->ExceptionClear(env);
267
JNU_ThrowOutOfMemoryError(env, "Could not create printer name");
268
return NULL;
269
}
270
271
// NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.
272
// unlink() must be caled to remove the file when finished using it.
273
filename = j2d_cupsGetPPD(name);
274
(*env)->ReleaseStringUTFChars(env, printer, name);
275
CHECK_NULL_RETURN(filename, NULL);
276
277
cls = (*env)->FindClass(env, "java/lang/String");
278
CHECK_NULL_RETURN(cls, NULL);
279
280
if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {
281
unlink(filename);
282
DPRINTF("CUPSfuncs::unable to open PPD %s\n", filename);
283
return NULL;
284
}
285
286
optionPage = j2d_ppdFindOption(ppd, "PageSize");
287
if (optionPage != NULL) {
288
nPages = optionPage->num_choices;
289
}
290
291
optionTray = j2d_ppdFindOption(ppd, "InputSlot");
292
if (optionTray != NULL) {
293
nTrays = optionTray->num_choices;
294
}
295
296
if ((nTotal = (nPages+nTrays) *2) > 0) {
297
nameArray = (*env)->NewObjectArray(env, nTotal, cls, NULL);
298
if (nameArray == NULL) {
299
unlink(filename);
300
j2d_ppdClose(ppd);
301
DPRINTF("CUPSfuncs::bad alloc new array\n", "")
302
(*env)->ExceptionClear(env);
303
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
304
return NULL;
305
}
306
307
for (i = 0; optionPage!=NULL && i<nPages; i++) {
308
choice = (optionPage->choices)+i;
309
utf_str = JNU_NewStringPlatform(env, choice->text);
310
if (utf_str == NULL) {
311
unlink(filename);
312
j2d_ppdClose(ppd);
313
DPRINTF("CUPSfuncs::bad alloc new string ->text\n", "")
314
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
315
return NULL;
316
}
317
(*env)->SetObjectArrayElement(env, nameArray, i*2, utf_str);
318
(*env)->DeleteLocalRef(env, utf_str);
319
utf_str = JNU_NewStringPlatform(env, choice->choice);
320
if (utf_str == NULL) {
321
unlink(filename);
322
j2d_ppdClose(ppd);
323
DPRINTF("CUPSfuncs::bad alloc new string ->choice\n", "")
324
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
325
return NULL;
326
}
327
(*env)->SetObjectArrayElement(env, nameArray, i*2+1, utf_str);
328
(*env)->DeleteLocalRef(env, utf_str);
329
}
330
331
for (i = 0; optionTray!=NULL && i<nTrays; i++) {
332
choice = (optionTray->choices)+i;
333
utf_str = JNU_NewStringPlatform(env, choice->text);
334
if (utf_str == NULL) {
335
unlink(filename);
336
j2d_ppdClose(ppd);
337
DPRINTF("CUPSfuncs::bad alloc new string text\n", "")
338
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
339
return NULL;
340
}
341
(*env)->SetObjectArrayElement(env, nameArray,
342
(nPages+i)*2, utf_str);
343
(*env)->DeleteLocalRef(env, utf_str);
344
utf_str = JNU_NewStringPlatform(env, choice->choice);
345
if (utf_str == NULL) {
346
unlink(filename);
347
j2d_ppdClose(ppd);
348
DPRINTF("CUPSfuncs::bad alloc new string choice\n", "")
349
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
350
return NULL;
351
}
352
(*env)->SetObjectArrayElement(env, nameArray,
353
(nPages+i)*2+1, utf_str);
354
(*env)->DeleteLocalRef(env, utf_str);
355
}
356
}
357
j2d_ppdClose(ppd);
358
unlink(filename);
359
return nameArray;
360
}
361
362
363
/*
364
* Returns list of page sizes and imageable area.
365
*/
366
JNIEXPORT jfloatArray JNICALL
367
Java_sun_print_CUPSPrinter_getPageSizes(JNIEnv *env,
368
jobject printObj,
369
jstring printer)
370
{
371
ppd_file_t *ppd;
372
ppd_option_t *option;
373
ppd_choice_t *choice;
374
ppd_size_t *size;
375
const char *filename = NULL;
376
int i;
377
jobjectArray sizeArray = NULL;
378
jfloat *dims;
379
380
const char *name = (*env)->GetStringUTFChars(env, printer, NULL);
381
if (name == NULL) {
382
(*env)->ExceptionClear(env);
383
JNU_ThrowOutOfMemoryError(env, "Could not create printer name");
384
return NULL;
385
}
386
387
// NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.
388
// unlink() must be called to remove the file after using it.
389
filename = j2d_cupsGetPPD(name);
390
(*env)->ReleaseStringUTFChars(env, printer, name);
391
CHECK_NULL_RETURN(filename, NULL);
392
if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {
393
unlink(filename);
394
DPRINTF("unable to open PPD %s\n", filename)
395
return NULL;
396
}
397
option = j2d_ppdFindOption(ppd, "PageSize");
398
if (option != NULL && option->num_choices > 0) {
399
// create array of dimensions - (num_choices * 6)
400
//to cover length & height
401
DPRINTF( "CUPSfuncs::option->num_choices %d\n", option->num_choices)
402
// +1 is for storing the default media index
403
sizeArray = (*env)->NewFloatArray(env, option->num_choices*6+1);
404
if (sizeArray == NULL) {
405
unlink(filename);
406
j2d_ppdClose(ppd);
407
DPRINTF("CUPSfuncs::bad alloc new float array\n", "")
408
(*env)->ExceptionClear(env);
409
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
410
return NULL;
411
}
412
413
dims = (*env)->GetFloatArrayElements(env, sizeArray, NULL);
414
if (dims == NULL) {
415
unlink(filename);
416
j2d_ppdClose(ppd);
417
(*env)->ExceptionClear(env);
418
JNU_ThrowOutOfMemoryError(env, "Could not create printer name");
419
return NULL;
420
}
421
for (i = 0; i<option->num_choices; i++) {
422
choice = (option->choices)+i;
423
// get the index of the default page
424
if (!strcmp(choice->choice, option->defchoice)) {
425
dims[option->num_choices*6] = (float)i;
426
}
427
size = j2d_ppdPageSize(ppd, choice->choice);
428
if (size != NULL) {
429
// paper width and height
430
dims[i*6] = size->width;
431
dims[(i*6)+1] = size->length;
432
// paper printable area
433
dims[(i*6)+2] = size->left;
434
dims[(i*6)+3] = size->top;
435
dims[(i*6)+4] = size->right;
436
dims[(i*6)+5] = size->bottom;
437
}
438
}
439
440
(*env)->ReleaseFloatArrayElements(env, sizeArray, dims, 0);
441
}
442
443
j2d_ppdClose(ppd);
444
unlink(filename);
445
return sizeArray;
446
}
447
448
/*
449
* Populates the supplied ArrayList<Integer> with resolutions.
450
* The first pair of elements will be the default resolution.
451
* If resolution isn't supported the list will be empty.
452
* If needed we can add a 2nd ArrayList<String> which would
453
* be populated with the corresponding UI name.
454
* PPD specifies the syntax for resolution as either "Ndpi" or "MxNdpi",
455
* eg 300dpi or 600x600dpi. The former is a shorthand where xres==yres.
456
* We will always expand to the latter as we use a single array list.
457
* Note: getMedia() and getPageSizes() both open the ppd file
458
* This is not going to scale forever so if we add anymore we
459
* should look to consolidate this.
460
*/
461
JNIEXPORT void JNICALL
462
Java_sun_print_CUPSPrinter_getResolutions(JNIEnv *env,
463
jobject printObj,
464
jstring printer,
465
jobject arrayList)
466
{
467
ppd_file_t *ppd = NULL;
468
ppd_option_t *resolution;
469
int defx = 0, defy = 0;
470
int resx = 0, resy = 0;
471
jclass intCls, cls;
472
jmethodID intCtr, arrListAddMID;
473
int i;
474
const char *name = NULL;
475
const char *filename = NULL;
476
477
intCls = (*env)->FindClass(env, "java/lang/Integer");
478
CHECK_NULL(intCls);
479
intCtr = (*env)->GetMethodID(env, intCls, "<init>", "(I)V");
480
CHECK_NULL(intCtr);
481
cls = (*env)->FindClass(env, "java/util/ArrayList");
482
CHECK_NULL(cls);
483
arrListAddMID =
484
(*env)->GetMethodID(env, cls, "add", "(Ljava/lang/Object;)Z");
485
CHECK_NULL(arrListAddMID);
486
487
name = (*env)->GetStringUTFChars(env, printer, NULL);
488
if (name == NULL) {
489
(*env)->ExceptionClear(env);
490
JNU_ThrowOutOfMemoryError(env, "Could not create printer name");
491
return;
492
}
493
494
495
// NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.
496
// unlink() must be called to remove the file after using it.
497
filename = j2d_cupsGetPPD(name);
498
(*env)->ReleaseStringUTFChars(env, printer, name);
499
CHECK_NULL(filename);
500
if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {
501
unlink(filename);
502
DPRINTF("unable to open PPD %s\n", filename)
503
}
504
resolution = j2d_ppdFindOption(ppd, "Resolution");
505
if (resolution != NULL) {
506
int matches = sscanf(resolution->defchoice, "%dx%ddpi", &defx, &defy);
507
if (matches == 2) {
508
if (defx <= 0 || defy <= 0) {
509
defx = 0;
510
defy = 0;
511
}
512
} else {
513
matches = sscanf(resolution->defchoice, "%ddpi", &defx);
514
if (matches == 1) {
515
if (defx <= 0) {
516
defx = 0;
517
} else {
518
defy = defx;
519
}
520
}
521
}
522
if (defx > 0) {
523
jobject rxObj, ryObj;
524
rxObj = (*env)->NewObject(env, intCls, intCtr, defx);
525
CHECK_NULL(rxObj);
526
ryObj = (*env)->NewObject(env, intCls, intCtr, defy);
527
CHECK_NULL(ryObj);
528
(*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj);
529
(*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj);
530
}
531
532
for (i = 0; i < resolution->num_choices; i++) {
533
char *resStr = resolution->choices[i].choice;
534
int matches = sscanf(resStr, "%dx%ddpi", &resx, &resy);
535
if (matches == 2) {
536
if (resx <= 0 || resy <= 0) {
537
resx = 0;
538
resy = 0;
539
}
540
} else {
541
matches = sscanf(resStr, "%ddpi", &resx);
542
if (matches == 1) {
543
if (resx <= 0) {
544
resx = 0;
545
} else {
546
resy = resx;
547
}
548
}
549
}
550
if (resx > 0 && (resx != defx || resy != defy )) {
551
jobject rxObj, ryObj;
552
rxObj = (*env)->NewObject(env, intCls, intCtr, resx);
553
CHECK_NULL(rxObj);
554
ryObj = (*env)->NewObject(env, intCls, intCtr, resy);
555
CHECK_NULL(ryObj);
556
(*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj);
557
(*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj);
558
}
559
}
560
}
561
562
j2d_ppdClose(ppd);
563
unlink(filename);
564
}
565
566